home *** CD-ROM | disk | FTP | other *** search
/ Resource for Source: C/C++ / Resource for Source - C-C++.iso / misc_src / cslib16b / doc / csdb.txt
Encoding:
Text File  |  1995-11-01  |  181.8 KB  |  5,580 lines

  1.  
  2.                                   March 1995
  3.  
  4.  
  5.  
  6.  
  7.  
  8.  
  9.  
  10.  
  11.  
  12.          The CS-libraries
  13.  
  14.          Version: 1.6.b
  15.  
  16.  
  17.  
  18.  
  19.          Theo van den Bout
  20.          P.O. Box 3303
  21.          2280 GH Rijswijk
  22.          The Netherlands
  23.  
  24.  
  25.  
  26.  
  27.  
  28.  
  29.  
  30.  
  31.  
  32.     Copyright (c) 1994,1995 by Combis, the Netherlands.
  33.     All Rights Reserved.
  34.  
  35.  
  36.  
  37.  
  38.                   1 Contents
  39.  
  40. 1 Contents . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  41.  
  42. 2 Preface. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  43.     2.1 Shareware. . . . . . . . . . . . . . . . . . . . . . . . . . . .
  44.     2.2 Contacting the Author. . . . . . . . . . . . . . . . . . . . . .
  45.     2.3 Registering. . . . . . . . . . . . . . . . . . . . . . . . . . .
  46.     2.4 Legal Matters. . . . . . . . . . . . . . . . . . . . . . . . . .
  47.     2.4.1 Disclaimer . . . . . . . . . . . . . . . . . . . . . . . .
  48.     2.4.2 Trademarks . . . . . . . . . . . . . . . . . . . . . . . .
  49.  
  50. 3 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  51.  
  52. 4 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  53.  
  54. 5 Debugging. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  55.  
  56. 6 Runtime Libraries. . . . . . . . . . . . . . . . . . . . . . . . . . .
  57.     6.1 Using the libraries. . . . . . . . . . . . . . . . . . . . . . .
  58.     6.2 Compiler options . . . . . . . . . . . . . . . . . . . . . . . .
  59.  
  60. 7 General Definitions & Functions. . . . . . . . . . . . . . . . . . . .
  61.     7.1 Portability. . . . . . . . . . . . . . . . . . . . . . . . . . .
  62.     7.2 Messages and errors. . . . . . . . . . . . . . . . . . . . . . .
  63.     7.3 Temporary Files. . . . . . . . . . . . . . . . . . . . . . . . .
  64.  
  65. 8 Buffering. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  66.  
  67. 9 PAGE-Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  68.     9.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . .
  69.     9.2 Background . . . . . . . . . . . . . . . . . . . . . . . . . . .
  70.     9.3 Storing data in the header-page. . . . . . . . . . . . . . . . .
  71.  
  72. 10 TBASE-class . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  73.     10.1 Introduction. . . . . . . . . . . . . . . . . . . . . . . . . .
  74.     10.2 Using TBASE . . . . . . . . . . . . . . . . . . . . . . . . . .
  75.     10.3 Creating a Database . . . . . . . . . . . . . . . . . . . . . .
  76.     10.4 Opening . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  77.     10.5 Closing . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  78.     10.6 Appending Records . . . . . . . . . . . . . . . . . . . . . . .
  79.     10.7 Deleting Records. . . . . . . . . . . . . . . . . . . . . . . .
  80.     10.8 Advanced Topics . . . . . . . . . . . . . . . . . . . . . . . .
  81.     10.8.1 Page Utilization. . . . . . . . . . . . . . . . . . . . .
  82.     10.8.2 Locating Records. . . . . . . . . . . . . . . . . . . . .
  83.     10.9 Miscellaneous functions . . . . . . . . . . . . . . . . . . . .
  84.     10.10 Functions in alphabetical order. . . . . . . . . . . . . . . .
  85.  
  86. 11 BTREE-class . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  87.     11.1 Introduction. . . . . . . . . . . . . . . . . . . . . . . . . .
  88.     11.2 BTREEx Classes. . . . . . . . . . . . . . . . . . . . . . . . .
  89.     11.3 Multiple Keys . . . . . . . . . . . . . . . . . . . . . . . . .
  90.     11.4 Current Pointer . . . . . . . . . . . . . . . . . . . . . . . .
  91.     11.5 Using Btrees. . . . . . . . . . . . . . . . . . . . . . . . . .
  92.     11.5.1 Creating. . . . . . . . . . . . . . . . . . . . . . . . .
  93.     11.5.2 Opening . . . . . . . . . . . . . . . . . . . . . . . . .
  94.     11.5.3 Inserting . . . . . . . . . . . . . . . . . . . . . . . .
  95.     11.5.4 Searching . . . . . . . . . . . . . . . . . . . . . . . .
  96.     11.5.5 Current . . . . . . . . . . . . . . . . . . . . . . . . .
  97.     11.5.6 Deleting. . . . . . . . . . . . . . . . . . . . . . . . .
  98.     11.5.7 Closing . . . . . . . . . . . . . . . . . . . . . . . . .
  99.     11.6 Functions in alphabetical order.. . . . . . . . . . . . . . . .
  100.  
  101. 12 CSDBGEN . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  102.     12.1 Introduction. . . . . . . . . . . . . . . . . . . . . . . . . .
  103.     12.2 Overview. . . . . . . . . . . . . . . . . . . . . . . . . . . .
  104.     12.3 Features. . . . . . . . . . . . . . . . . . . . . . . . . . . .
  105.     12.4 Limitations . . . . . . . . . . . . . . . . . . . . . . . . . .
  106.     12.5 Definition file . . . . . . . . . . . . . . . . . . . . . . . .
  107.     12.6 Tokenizing. . . . . . . . . . . . . . . . . . . . . . . . . . .
  108.     12.6.1 How does it work? . . . . . . . . . . . . . . . . . . . .
  109.     12.7 When is a substring indexed?. . . . . . . . . . . . . . . . . .
  110.     12.8 Export to dBASE . . . . . . . . . . . . . . . . . . . . . . . .
  111.     12.9 Exporting/Importing to/from ASCII . . . . . . . . . . . . . . .
  112.     12.10 Starting a new database. . . . . . . . . . . . . . . . . . . .
  113.     12.11 Opening a database . . . . . . . . . . . . . . . . . . . . . .
  114.     12.12 Current Record . . . . . . . . . . . . . . . . . . . . . . . .
  115.     12.13 Accessing fields . . . . . . . . . . . . . . . . . . . . . . .
  116.     12.14 DATE fields. . . . . . . . . . . . . . . . . . . . . . . . . .
  117.     12.15 Changing the record layout.. . . . . . . . . . . . . . . . . .
  118.     12.16 Member functions in alphabetical order . . . . . . . . . . . .
  119.     12.17 Warning. . . . . . . . . . . . . . . . . . . . . . . . . . . .
  120.     12.18 Example. . . . . . . . . . . . . . . . . . . . . . . . . . . .
  121.  
  122. 13 VRAM  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  123.     13.1 Introduction. . . . . . . . . . . . . . . . . . . . . . . . . .
  124.     13.2 Creating. . . . . . . . . . . . . . . . . . . . . . . . . . . .
  125.     13.3 Opening & Closing . . . . . . . . . . . . . . . . . . . . . . .
  126.     13.4 VRAM Pointers . . . . . . . . . . . . . . . . . . . . . . . . .
  127.     13.5 Fragmentation . . . . . . . . . . . . . . . . . . . . . . . . .
  128.     13.6 Root. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  129.     13.7 Functions in Alphabetical order.. . . . . . . . . . . . . . . .
  130.  
  131. 14 VBASE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  132.     14.1 Introduction. . . . . . . . . . . . . . . . . . . . . . . . . .
  133.     14.2 Using VBASE.. . . . . . . . . . . . . . . . . . . . . . . . . .
  134.     14.3 Relocating records. . . . . . . . . . . . . . . . . . . . . . .
  135.     14.4 Limitations.. . . . . . . . . . . . . . . . . . . . . . . . . .
  136.     14.5 Functions in alphabetical order.. . . . . . . . . . . . . . . .
  137.  
  138. 15 VBAXE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  139.     15.1 Introduction. . . . . . . . . . . . . . . . . . . . . . . . . .
  140.     15.2 Working.. . . . . . . . . . . . . . . . . . . . . . . . . . . .
  141.     15.3 Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  142.     15.4 Prototypes. . . . . . . . . . . . . . . . . . . . . . . . . . .
  143.  
  144. 16 CSDIR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  145.  
  146. 17 CSINFO. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  147.  
  148. 18 CSERROR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  149.  
  150. 19 CSADD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  151.     19.1 Source. . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  152.     19.2 Openings screen . . . . . . . . . . . . . . . . . . . . . . . .
  153.     19.3 Features. . . . . . . . . . . . . . . . . . . . . . . . . . . .
  154.  
  155. 20 CSTOOLS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  156.     20.1 Introduction  . . . . . . . . . . . . . . . . . . . . . . . . .
  157.  
  158. 21 CSKEYS. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  159.     21.1 CSKEYS.exe. . . . . . . . . . . . . . . . . . . . . . . . . . .
  160.  
  161. 22 HEAP. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  162.     22.1 Purpose . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  163.     22.2 When to use it? . . . . . . . . . . . . . . . . . . . . . . . .
  164.     22.3 Using HEAP. . . . . . . . . . . . . . . . . . . . . . . . . . .
  165.     22.4 Functions in alphabetical order.. . . . . . . . . . . . . . . .
  166.  
  167. 23 Alloc-Logging . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  168.     23.1 Introduction. . . . . . . . . . . . . . . . . . . . . . . . . .
  169.     23.2 Replacements. . . . . . . . . . . . . . . . . . . . . . . . . .
  170.     23.3 Logging . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  171.     23.4 Memory Leaks. . . . . . . . . . . . . . . . . . . . . . . . . .
  172.  
  173. 24 CSEDSTR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  174.  
  175. 25 CSWINDOWS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  176.     25.1 Introduction. . . . . . . . . . . . . . . . . . . . . . . . . .
  177.     25.2 General Information . . . . . . . . . . . . . . . . . . . . . .
  178.     25.3 The C++ version, the class WINDOW . . . . . . . . . . . . . . .
  179.     25.3.1 Syntax of the MEMBER functions. . . . . . . . . . . . . .
  180.     25.4 The C version . . . . . . . . . . . . . . . . . . . . . . . . .
  181.     25.4.1 Example . . . . . . . . . . . . . . . . . . . . . . . . .
  182.     25.5 Syntax of the C functions . . . . . . . . . . . . . . . . . . .
  183.     25.6 Working within a Window . . . . . . . . . . . . . . . . . . . .
  184.     25.7 File Browsing . . . . . . . . . . . . . . . . . . . . . . . . .
  185.  
  186. 26 CSMENU. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  187.     26.1 General Information . . . . . . . . . . . . . . . . . . . . . .
  188.     26.2 Defining a menu . . . . . . . . . . . . . . . . . . . . . . . .
  189.     26.3 Connecting menus. . . . . . . . . . . . . . . . . . . . . . . .
  190.     26.4 Displaying the menu . . . . . . . . . . . . . . . . . . . . . .
  191.     26.5 Using menus . . . . . . . . . . . . . . . . . . . . . . . . . .
  192.     26.6 Removing the menu . . . . . . . . . . . . . . . . . . . . . . .
  193.  
  194. 27 CSPANEL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  195.     27.1 Purpose . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  196.     27.2 General Information . . . . . . . . . . . . . . . . . . . . . .
  197.     27.3 Public member functions . . . . . . . . . . . . . . . . . . . .
  198.     27.4 Dates . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  199.     27.5 Fields. . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  200.     27.6 Using the panels. . . . . . . . . . . . . . . . . . . . . . . .
  201.     27.7 Data validation . . . . . . . . . . . . . . . . . . . . . . . .
  202.     27.7.1 Min and Max . . . . . . . . . . . . . . . . . . . . . . .
  203.     27.7.2 Reset Max & Min . . . . . . . . . . . . . . . . . . . . .
  204.     27.7.3 Templates . . . . . . . . . . . . . . . . . . . . . . . .
  205.  
  206. 28 Registration Form . . . . . . . . . . . . . . . . . . . . . . . . . .
  207.  
  208.                   2 Preface
  209.  
  210.  
  211. This is a shareware package consisting mainly of two distinct libraries.
  212. The libraries are to be used with Borland C++ 3.1 or later. Both
  213. MS-DOS and Windows applications are supported.
  214.  
  215. The libraries are intended for programmers who need some kind of
  216. database in their application but are reluctant to use any of the vast
  217. DBMS's. The supplied classes are doing all their IO themselves, apart
  218. from the OS, no other software is needed.
  219.  
  220. One library concentrates on supplying a user-interface for the non-
  221. Windows programmer, the other library supplies the classes necessary
  222. to build database applications. An application generator is used to
  223. produce the source for the more complicated databases with indexes
  224. and fields.
  225.  
  226.  
  227. 2.1 Shareware
  228.  
  229. This software is distributed as 'Shareware' which means you are free to
  230. copy and share these files.
  231. It is a fully functioning version, but it does NOT include the complete
  232. package.
  233.  
  234.  
  235. 2.2 Contacting the Author
  236.  
  237. You can reach me, preferably, by E-mail. The address is:
  238. T.P.vandenBout@et.tudelft.nl.
  239.  
  240. If you don't have E-mail access you can reach me by traditional mail:
  241.     Theo van den Bout
  242.     P.O. Box 3303
  243.     2280 GH Rijswijk
  244.     The Netherlands
  245.  
  246. For urgent matters only, phone me at +31703960172.
  247. Please remember, it is GMT +100 over here. I have serious problems
  248. with being woken in the middle of the night!
  249.  
  250.  
  251. 2.3 Registering
  252.  
  253. When you send  f 200.- (200 Dutch guilders) or $ 125 (125 American
  254. Dollars) you will become a 'registered user'.
  255.  
  256. This means you will receive
  257.     - the latest version
  258.     - all the libraries
  259.     - support.
  260.     - a nice manual.
  261.  
  262.  
  263. Send money, check or money order to:
  264.  
  265.          Combis
  266.          P.O. Box 3303
  267.          2280 GH Rijswijk
  268.          The Netherlands
  269.  
  270. You will find a registration form at the end of this documentation.
  271. 2.4 Legal Matters
  272.  
  273. 2.4.1 Disclaimer
  274.  
  275. EXCEPT WHEN OTHERWISE STATED IN WRITING THE
  276. COPYRIGHT HOLDER AND/OR OTHER PARTIES PROVIDE THE
  277. PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
  278. EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
  279. IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  280. A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY
  281. AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD
  282. THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
  283. ALL NECESSARY SERVICING, REPAIR OR CORRECTION. IN NO
  284. EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO
  285. IN WRITING WILL THE COPYRIGHT HOLDER BE LIABLE TO YOU
  286. FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL,
  287. INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF
  288. THE USE OR INABILITY TO USE THE SOFTWARE (INCLUDING BUT
  289. NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED
  290. INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
  291. PARTIES), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN
  292. ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
  293.  
  294. 2.4.2 Trademarks
  295.  
  296. IBM is a registered trademark of International Business Machines
  297. Corporation.
  298. MS-DOS and Windows are registered trademarks of Microsoft
  299. Corporation.
  300. Borland C/C++ and dBASE are registered trademarks of Borland
  301. International Inc.
  302.  
  303.  
  304.  
  305.  
  306.  
  307.  
  308.  
  309.  
  310.  
  311.  
  312.  
  313.                     Part
  314.  
  315.                     One
  316.  
  317.  
  318.  
  319.  
  320.  
  321.  
  322.  
  323.  
  324.  
  325.  
  326.  
  327.  
  328.  
  329.  
  330.  
  331.  
  332.  
  333.  
  334.  
  335.  
  336.  
  337.  
  338.     The next part of the documentation gives an overview of this
  339.                 package.
  340.     It will also discuss the PAGE- and the BUFFER-class from which all
  341.               database classes are derived.
  342.       Some other topics of general interest are covered too.
  343.                 3 Introduction
  344.  
  345.  
  346. This package mainly consists of two almost independent libraries. The
  347. library called CSDB, is the far most important one. The other one, CSA,
  348. is kind-of 'thrown in for free'. Despite this, it contains important general
  349. purpose functions heavily used by the CSDB library.
  350.  
  351. The main purpose of this library is to provide a C++ programmer with
  352. the utilities to incorporate databases in its applications without being
  353. forced to use one of the huge DBMS's currently on the market. The
  354. CSDB-library contains the classes needed to fulfil this purpose.
  355. Therefore, the emphasis in this documentation is on the CSDB library.
  356.  
  357. The CSA library is intended to provide the non-Windows programmer
  358. with the tools to easily build a user interface. The library therefore
  359. contains classes for menu's, forms and windows.
  360.  
  361. As an example an address-book type of application is included. This
  362. should give a quick impression of the purpose and capabilities of the
  363. classes.
  364.  
  365. Although this package is shareware, it still contains a fully functioning
  366. version. However, not all the libraries are included. What is shipped is
  367. the library with the debug-version of the large memory model. As
  368. explained further on, there are two versions of each library. One
  369. containing a lot of code to trap errors, and a second one optimized for
  370. speed.
  371. The library in this shareware package will therefore produce somewhat
  372. larger and slower applications then needed. Please, do keep this in
  373. mind.
  374.  
  375.                   4 Overview
  376.  
  377. This page will try to give a quick overview of the contents of this
  378. package.
  379.  
  380. The CSDB-library contains (among others) the following classes:
  381.     TBASE:        A class for reading and wrtiting records.
  382.     BTREE:        A btree+ to be used as an index.
  383.     VRAM:        A 'database' organized as a heap.
  384.     VBASE:        Variable length records.
  385.     VBAXE:        As VBASE but for very large databases.
  386.  
  387. The CSA-library contains general-purpose functions and classes to
  388. build a character oriented user-interface. Among others, the following
  389. classes are included:
  390.     WINDOW:        Text windows.
  391.     MENU:        A menu system.
  392.     PANEL:        Data entry screens.
  393.     HEAP:        To efficiently allocate many small blocks from the
  394.             heap.
  395.  
  396. Command line utilities (DOS):
  397.     CSDIR:        Lists the databases in a directory.
  398.     CSINFO:        Displays information about a database.
  399.     CSDBGEN:        Important program-generator.
  400.     CSERROR:        Utility to convert the error file to C++ source.
  401.     CSKEYS:        Displays the return value of the cskey() function.
  402.     CSMALLOC:        Tests the allocation log for memory leaks.
  403.  
  404. Documentation:
  405.     CSDB.txt:        This documentation in ASCII format.
  406.  
  407. Examples:
  408.     CSADDRESS:        A nice address database (DOS).
  409.     CSMENDEM:        Demonstration of the MENU class.
  410.     CSPANDEM:        Demonstration of the PANEL class.
  411.  
  412.                  5 Debugging
  413.  
  414.  
  415. Of each library two versions exist, one to be used during debugging
  416. and one intended for normal 'production'. The difference is that in the
  417. debug-version a lot more tests are done, and so many more errors are
  418. reported.
  419.  
  420. The idea is to use the debug version during development and
  421. recompile with the production version when ready. The debug version
  422. is identical to the production version, but with additional tests. The
  423. 'working code' is 100% identical. This means there are no subtle
  424. differences between the two versions.
  425.  
  426. The production version however can be substantial faster, up to two
  427. times, depending on the circumstances.
  428.  
  429. To give an example:
  430.     The TBASE class has functions to read a record from the
  431.     database. For this function to operate properly, the class/database
  432.     needs to be 'opened'. In the debug version this is tested with every
  433.     call to the read function. In the production version this is never
  434.     tested. Note that in a decently written and tested application this
  435.     error should not occur. Errors with the open function should be
  436.     trapped much earlier.
  437.  
  438. There are many more errors like this. Errors that should not occur when
  439. the application is tested and (almost) ready but which can easily
  440. emerge in the development stage.
  441.  
  442.                  6 Runtime Libraries
  443.  
  444. The libraries are to be used with the Borland C++ compilers. Versions
  445. exist for both MS-DOS and Windows.
  446.  
  447. With MS-DOS three memory models are supported: compact, large and
  448. huge. These are the memory models which use far data.
  449. The same applies for MS-Windows but with the exception of the huge
  450. memory model. Windows doesn't allow that.
  451.  
  452. ╔══════════════╤═════════════╤═══════════╤════════════╤════════════════╗
  453. ║ Name           │Operating    │ Library     │ Memory     │ Type           ║
  454. ║           │System         │         │ Model      │            ║
  455. ╟──────────────┼─────────────┼───────────┼────────────┼────────────────╢
  456. ║ CSDACP       │Dos         │ CSA     │ Compact    │ Production     ║
  457. ╟──────────────┼─────────────┼───────────┼────────────┼────────────────╢
  458. ║ CSDACD       │Dos         │ CSA     │ Compact    │ Debug           ║
  459. ╟──────────────┼─────────────┼───────────┼────────────┼────────────────╢
  460. ║ CSDALP       │Dos         │ CSA     │ Large      │ Production     ║
  461. ╟──────────────┼─────────────┼───────────┼────────────┼────────────────╢
  462. ║ CSDALD       │Dos         │ CSA     │ Large      │ Debug           ║
  463. ╟──────────────┼─────────────┼───────────┼────────────┼────────────────╢
  464. ║ CSDAHP       │Dos         │ CSA     │ Huge       │ Production     ║
  465. ╟──────────────┼─────────────┼───────────┼────────────┼────────────────╢
  466. ║ CSDAHD       │Dos         │ CSA     │ Huge       │ Debug           ║
  467. ╚══════════════╧═════════════╧═══════════╧════════════╧════════════════╝
  468.  
  469.  
  470. ╔══════════════╤═════════════╤═══════════╤════════════╤════════════════╗
  471. ║ Name           │Operating    │ Library     │ Memory     │ Type           ║
  472. ║           │System         │         │ Model      │            ║
  473. ╟──────────────┼─────────────┼───────────┼────────────┼────────────────╢
  474. ║ CSWACP       │Windows      │ CSA     │ Compact    │ Production     ║
  475. ╟──────────────┼─────────────┼───────────┼────────────┼────────────────╢
  476. ║ CSWACD       │Windows      │ CSA     │ Compact    │ Debug           ║
  477. ╟──────────────┼─────────────┼───────────┼────────────┼────────────────╢
  478. ║ CSWALP       │Windows      │ CSA     │ Large      │ Production     ║
  479. ╟──────────────┼─────────────┼───────────┼────────────┼────────────────╢
  480. ║ CSWALD       │Windows      │ CSA     │ Large      │ Debug           ║
  481. ╚══════════════╧═════════════╧═══════════╧════════════╧════════════════╝
  482.  
  483. ╔══════════════╤═════════════╤═══════════╤════════════╤════════════════╗
  484. ║ Name           │Operating    │ Library     │ Memory     │ Type           ║
  485. ║           │System         │         │ Model      │            ║
  486. ╟──────────────┼─────────────┼───────────┼────────────┼────────────────╢
  487. ║ CSDDCP       │Dos         │ CSDB     │ Compact    │ Production     ║
  488. ╟──────────────┼─────────────┼───────────┼────────────┼────────────────╢
  489. ║ CSDDCD       │Dos         │ CSDB     │ Compact    │ Debug           ║
  490. ╟──────────────┼─────────────┼───────────┼────────────┼────────────────╢
  491. ║ CSDDLP       │Dos         │ CSDB     │ Large      │ Production     ║
  492. ╟──────────────┼─────────────┼───────────┼────────────┼────────────────╢
  493. ║ CSDDLD       │Dos         │ CSDB     │ Large      │ Debug           ║
  494. ╟──────────────┼─────────────┼───────────┼────────────┼────────────────╢
  495. ║ CSDDHP       │Dos         │ CSDB     │ Huge       │ Production     ║
  496. ╟──────────────┼─────────────┼───────────┼────────────┼────────────────╢
  497. ║ CSDDHD       │Dos         │ CSDB     │ Huge       │ Debug           ║
  498. ╚══════════════╧═════════════╧═══════════╧════════════╧════════════════╝
  499.  
  500.  
  501. ╔══════════════╤═════════════╤═══════════╤══════════════╤══════════════╗
  502. ║ Name           │Operating    │ Library     │ Memory    │ Type           ║
  503. ║           │System         │         │ Model    │           ║
  504. ╟──────────────┼─────────────┼───────────┼──────────────┼──────────────╢
  505. ║ CSWDCP       │Windows      │ CSDB     │ Compact    │ Production   ║
  506. ╟──────────────┼─────────────┼───────────┼──────────────┼──────────────╢
  507. ║ CSWDCD       │Windows      │ CSDB     │ Compact    │ Debug        ║
  508. ╟──────────────┼─────────────┼───────────┼──────────────┼──────────────╢
  509. ║ CSWDLP       │Windows      │ CSDB     │ Large    │ Production   ║
  510. ╟──────────────┼─────────────┼───────────┼──────────────┼──────────────╢
  511. ║ CSWDLD       │Windows      │ CSDB     │ Large    │ Debug        ║
  512. ╚══════════════╧═════════════╧═══════════╧══════════════╧══════════════╝
  513.  
  514. Of course you have noticed there is a system in these names:
  515.     csOLMT.lib
  516.     with:
  517.     O:  Operating System
  518.         D is DOS,
  519.         W is Windows
  520.     L:  Library
  521.         A is CSA
  522.         D is CSDB
  523.     M:  Memory model
  524.         C is Compact
  525.         L is Large
  526.         H is Huge
  527.     T:   Type
  528.         P is Production
  529.         D is Debug
  530.  
  531. In the shareware distribution only two libraries are found:
  532.     CSD.lib:    For Dos. This is a combination of
  533.         CSDDLD.lib and CSDALD.lib.
  534.     CSW.lib:    For Windows. This is a combination of
  535.         CSWDLD.lib and CSWALD.lib.
  536.  
  537.  
  538. 6.1 Using the libraries
  539.  
  540. Unless you are using only the classes from the CSA collection you
  541. always have to link in two libraries.
  542.  
  543. Example:
  544.     Suppose you start developing in the large memory model under
  545.     DOS. Link CSDDLD.lib and CSDALD.lib. It is best to link
  546.     CSDDLD.lib first.
  547.  
  548.     When the application is appropriately debugged, it is time to start
  549.     using the CSDDLP.lib and the CSDALP.lib.
  550.  
  551.     After that, you may consider porting to Windows. Assuming you
  552.     can skip the debugging phase there, link the CSWDLP.lib and the
  553.     CSWALP.lib.
  554.  
  555. Users of the shareware distribution have far less choice:
  556. use CSD.lib for DOS and CSW.lib for windows.
  557.  
  558.  
  559. 6.2 Compiler options
  560.  
  561. The production library is compiled with:
  562.     - No tests for stack overflow.
  563.     - Optimized for speed.
  564.     - No overlays.
  565.     - 80286 instructions.
  566.     - Signed characters with BC 3.1
  567.     - 'Undefined' characters with BC 4.x.
  568.     - Byte alignment.
  569.  
  570. The debug library is compiled with tests for stack overflow. Apart from
  571. that it's identical. (Using the same compiler options that is.)
  572.  
  573. The Windows' version is compiled with 80386 instructions.
  574.  
  575. Make sure you are using the right type of characters. If not,
  576. you will  experience linking problems.
  577. Don't use word-alignment.
  578.  
  579.               7 General Definitions & Functions
  580.  
  581.  
  582. 7.1 Portability
  583.  
  584. A series of typedefs is used to create portable variable types.
  585.  
  586.  
  587.      S8:    Singed 8 bit,    (singed char)
  588.      U8:    Unsigned 8 bit, (unsigned char)
  589.      S16:    Singed 16 bit    (int)
  590.      U16:    Unsigned 16 bit (unsigned int )
  591.      S32:    Singed 32 bit    (long)
  592.      U32:    Unsigned 32 bit (unsigned long)
  593.  
  594.      uchar    unsigned char
  595.      schar    signed char
  596.      CSCHAR    char
  597.  
  598.  
  599. However, on many occasions (particularly function returns) the range of
  600. the variable is not all that much important. In these cases integers are
  601. used because that's normally the fastest.
  602.  
  603.  
  604. 7.2 Messages and errors
  605.  
  606. A special set of functions is used to display errors, messages and the
  607. alike. To avoid confusion: these are 'normal' C-type functions, not
  608. public functions of some message class.
  609.  
  610. All these functions eventually display their messages through a call to
  611. csmess_disp(char *).
  612. By default (under DOS), this function writes all the messages to the
  613. console by using the standard cputs() function.
  614. With WINDOWS, a standard message box is called.
  615.  
  616. Fortunate, this function can easily be altered.
  617. Before being displayed by the csmess_disp() function, all the messages
  618. are converted into a single string. This makes changing the message
  619. function very easy. Only a single function, which accepts a character
  620. pointer, needs to be supplied.
  621.  
  622. The next function is intended to do that:
  623.  
  624. void csmess_set_fun( void (* fun)(char *));
  625.  
  626.  
  627. //  Example (Dos):
  628.  
  629.       void display(char *s)
  630.       {
  631.      //  This function is going to be used
  632.      //  To display messages.
  633.      printf("%s",s);
  634.       }
  635.  
  636.  
  637.       void main(void)
  638.       {
  639.       csmess_set_fun(display);
  640.       //  From now on, all the messages are
  641.       //  displayed through a call to the
  642.       //  'display()' function.
  643.      }
  644.  
  645.  
  646.  
  647. To restore the default, the next function can be used:
  648.  
  649. void csmess_reset_fun(void);
  650.  
  651.  
  652. //  Example:
  653.  
  654.       void main(void)
  655.       {
  656.       csmess_reset_fun();
  657.       // Restores the default
  658.       // Display function.
  659.       }
  660.  
  661.  
  662. void csmess_off(void);
  663.         With this function, messages can be suppressed.
  664.         Whether you are using the standard message
  665.         function or has it replaced with your own, after a call
  666.         to this function no message will be displayed.
  667.  
  668. void csmess_on(void);
  669.         To be used in conjunction with the csmess_off()
  670.         function. After a call to 'csmess_on()' messages will
  671.         be displayed again.
  672.  
  673. int csmess_onoff(void);
  674.         Returns TRUE if message displaying is switched on.
  675.         FALSE otherwise.
  676.  
  677. void csmess_onoff(int sw);
  678.         If called with sw unequal zero, messages will be
  679.         displayed. Otherwise not.
  680.  
  681.  
  682. 7.3 Temporary Files.
  683.  
  684. Temporary files are created through the use of the cstmpname()
  685. function, discussed in the CSTOOLS chapter.
  686. This means, the environment variables TEMP and TMP are checked    to
  687. determine which subdirectory is going to be used.
  688. Temporary files can be as large as the databases they are belonging
  689. to. So, make sure the environment variables don' t point to some small
  690. ram-disk or an insufficient large partition.
  691.  
  692.                  8 Buffering
  693.  
  694.  
  695. All the disk IO is done by a very solid buffer-system. All the database
  696. classes have a function which makes it possible to control the amount
  697. of memory used for buffering.
  698.  
  699. This amount is not allocated right from the start but is interpreted as a
  700. maximum. This means that buffers are allocated on the fly, up to this
  701. limit. The advantage is that the maximum may never be reached,
  702. saving valuable memory for other purposes.
  703. Of course there is also a drawback. The problem is that there is no way
  704. the classes can predict how much memory needs to be reserved for
  705. the remaining part of the program. The buffering-system itself will stop
  706. allocating memory when the heap is exhausted, but if dynamic memory
  707. allocation is used somewhere further on, the program may still
  708. terminate with a message of the type 'out of memory'.
  709.  
  710. It should be noted that this is only a problem with the MS-DOS
  711. operating system. Any other (real) operating system uses virtual
  712. memory which makes sure that your program will work with any
  713. reasonable assumption about the available amount of memory. For
  714. performance reasons, however, it is better not to rely on virtual
  715. memory. Let the classes do the buffering, not the operating system.
  716.  
  717. What all this means is that with MS-DOS you have to be
  718. careful about using a large amount of ram for buffering.
  719.  
  720.  
  721.                  9 PAGE-Class
  722.  
  723. 9.1 Introduction
  724.  
  725. The PAGE-class constitutes a  kind of 'foundation'  for most of the
  726. other classes in the CSDB library.  It is derived from a class 'BUFF'
  727. which takes care of the required buffering. (Described in the previous
  728. chapter.)
  729.  
  730. The idea is to do disk IO in chunks of 2 Kb. This is close to the optimal
  731. size for the average harddisk. These blocks are kept aligned with the
  732. sectors of the harddisk, which improves speed considerablely.
  733. A harddisk always reads an entire sector, even if you only need, let's
  734. say, 10 bytes. Things become even worse if the 10 bytes you are
  735. requesting just happen to cross a sector boundary. In that case your
  736. harddisk will read 2 entire sectors. Assuming a sector is 1024 bytes,
  737. this means that 2*1024=2048 bytes are read just to obtain your 10
  738. bytes!
  739.  
  740. To avoid this kind of inefficiency the PAGE-class does its disk IO in
  741. pages of 2048 bytes while making sure every page is aligned with the
  742. harddisk sectors. This also means that the indispensable file-header
  743. has to be at least one sector. To avoid complications, a file-header is
  744. used which has the same size as a page, 2048 bytes by default.
  745.  
  746. It should be noted that this entire scene is undone by using a
  747. disk compression utility, like double space, stacker and the
  748. alike.
  749.  
  750. Therefore, if you are concerned about performance, it is better not to
  751. use these utilities. More over, a disk compressor will slow down your
  752. application considerablely when several files are used heavily 'at the
  753. same time'.  This situation will almost inevitably arise with any serious
  754. application which uses more then one database, or even a single
  755. database with many indexes.
  756.  
  757.  
  758. 9.2 Background
  759.  
  760. One of the special features implemented in the PAGE-class is the
  761. 'background()' function.
  762. This function is intended to make good use of the idle time waiting for
  763. the user's input. It is guaranteed to return in a very short period of time,
  764. doing at most one disk IO with every call.
  765.  
  766.  
  767. By result you can write code like:
  768.  
  769.     while(!kbhit()) CLASS.background();
  770.  
  771.  
  772. E.g. the background() function supplied by the PAGE class writes 'dirty'
  773. buffers back to disk. This is done one-by-one. Each call will write at
  774. most one buffer. Because of this, the application user will hardly notice
  775. anything, while in the future the application doesn't have to spend time
  776. writing buffers back to disk.
  777.  
  778. The function will return a value greater then zero if something has been
  779. done and zero otherwise.
  780. After some time the class runs out of things to do and it becomes
  781. pointless to spend CPU-time on calls to the background() function. By
  782. testing the return value, this can be avoided.
  783.  
  784. In some derived classes, the background() function is overloaded to do
  785. additional house keeping.
  786.  
  787.  
  788. 9.3 Storing data in the header-page
  789.  
  790. As explained above, the header page is quite large. This page is used
  791. to store al kind of important variables. However, there is still much
  792. space left. Of the 2048 bytes only about 170 are used.
  793.  
  794. An application using databases is like to have some variables of his
  795. own which need to be maintained between close/open sequences. It
  796. seems the remaining space in the header page is a convenient place
  797. store such data. This can save you an additional configuration file and
  798. all the error trapping involved.
  799.  
  800. To aid in this, three functions are made public:
  801.     int data_2_header(void * ptr,U16 length);
  802.     int header_2_data(void * ptr,U16 length);
  803.     U16 max_data_in_header(void);
  804.  
  805. U16 max_data_in_header(void);
  806.         This function returns the maximum number of bytes
  807.         which will still fit in the header page. This is simply
  808.         the size of the header-page minus what is used to
  809.         store the variables of the class.
  810.         The class needs to be open.
  811.  
  812. int data_2_header(void * buffer,U16 length);
  813.         Copies data from buffer 'buffer' to the empty space in
  814.         the header page. The variable 'length' indicates the
  815.         number of bytes to be copied. This figure is not
  816.         stored anywhere. It is the programmers' responsibility
  817.         to retrieve the right number of bytes later on.
  818.         The class needs to be open.
  819.  
  820. int header_2_data(void * buffer,U16 length);
  821.         The counterpart of the previous function. This
  822.         function copies 'length' number of bytes from the
  823.         header page to 'buffer'.
  824.         The class needs to be open.
  825.  
  826.  
  827.  
  828.  
  829.  
  830.  
  831.  
  832.  
  833.  
  834.                     Part
  835.  
  836.                     Two
  837.  
  838.  
  839.  
  840.  
  841.  
  842.  
  843.  
  844.  
  845.  
  846.  
  847.  
  848.  
  849.  
  850.  
  851.  
  852.  
  853.  
  854.  
  855.  
  856.  
  857.  
  858.  
  859.     Part Two of the documentation will explain how this library can be
  860.          used to build traditional relational databases.
  861.        To do so, it uses a TBASE class to store records and a BTREE
  862.                 class for indexes.
  863.        A program generator, CSDBGEN, is discussed which 'automates'
  864.      the process of building more complex databases out of TBASE and
  865.                   BTREE.
  866.      These two classes can also be used seperately. In particular the
  867.    BTREE class is very useful. It is really easy expandable and can be
  868.      tailored to a specific purpose by supplying one single function.
  869.      Simple databases with only one index can be build with just the
  870.                    BTREE class.
  871.  
  872.  
  873.                 10 TBASE-class
  874.  
  875.  
  876. 10.1 Introduction
  877.  
  878. The TBASE class is intended as a simple, fast way to access records
  879. on disk. It assumes a fixed record size and does its IO on a record-by-
  880. record basis (contrary to field-by-field).
  881.  
  882. This means:
  883.     1) TBASE is unaware of something like 'fields'. The idea is to use
  884.     a C structure as record and to do all the accessing of fields
  885.     with the standard C operators. This approach is undoubtedly
  886.     faster then supporting access on a field-by-field basis as done
  887.     by dBASE.
  888.     2) No indexes. TBASE just reads or writes records, nothing else.
  889.  
  890. NOTE:    From this it is clear that with the TBASE class alone no decent
  891.     database application can be build. Therefore, a separate
  892.     BTREE class is supplied which can be used as an index.
  893.     To glue it all together, a program generator, CSDBGEN, is
  894.     available. Because C isn't particularly bright in handling strings
  895.     and date's, the program generator takes care of that too.
  896.  
  897.  
  898. 10.2 Using TBASE
  899.  
  900. The next small example gives an impression of how to use the class.
  901.  
  902. As can be seen from this example, there is no 'record pointer' as in
  903. dBASE. The functions to read and write a record, simply take an
  904. additional parameter indicating the record number.
  905.  
  906.  
  907.  
  908. // A very simple example.
  909.  
  910.   # include "CSTBASE.H"
  911.  
  912.    void main(void)
  913.    {
  914.        typedef struct
  915.        {
  916.     char name[20];        // The field 'name'
  917.     char street[40];    // The field 'street'
  918.     long salary;        // The field 'salary'
  919.     // All the other fields you may require.
  920.        }record;         // The record layout is now defined.
  921.  
  922.        TBASE db;
  923.        record rec;
  924.        db.open("demo.dbf",110); // Assuming the file is already created.
  925.                 // Use 110 kB for buffering.
  926.        db.read_rec(9,&rec);    // Read record number 9 into
  927.                 // variable 'rec'.
  928.        rec.salary=0;        // Change salary.
  929.        db.write_rec(9,&rec);    // Write the record back to position 9.
  930.                 // (Any other position is also possible.)
  931.        db.close();        // Is also done automatically
  932.                 // by the class destructor.
  933.     }
  934.  
  935.  
  936.  
  937.  
  938.  
  939. 10.3 Creating a Database
  940.  
  941. Before a database can be used it has to be 'created'. This is done
  942. through a call to the 'define()' function. Of course this is needed only
  943. once.
  944. Because TBASE doesn't use fields, the function takes only two
  945. parameters: the filename of the database, and the record size.
  946.  
  947. Syntax: int define(char * name,U16 reclen);
  948.  
  949.  
  950. //   This example creates a database 'demo.dbf'.
  951.  
  952.  
  953.     #include "CSTBASE.H"
  954.     void main(void)
  955.     {
  956.        typedef struct
  957.        {
  958.       char name[20];
  959.       char street[40];
  960.       char city[25];
  961.        } record;
  962.  
  963.        TBASE db;
  964.        db.define("demo.dbf",sizeof(record));
  965.    }
  966.  
  967.  
  968.  
  969. 10.4 Opening
  970.  
  971. Before a record can be read, the database has to be opened through a
  972. call to the open() function.
  973.  
  974. This open() function also takes a parameter indicating the amount of
  975. memory to be used for buffering. The memory for the buffers is NOT
  976. allocated at the moment of the call to open(), but during the use of the
  977. database. Memory is allocated when needed, up to this maximum.
  978.  
  979. As explained in the chapter about buffering, using up too
  980. much memory for buffering is dangerous on an Operating
  981. System like MS-DOS with no virtual memory.
  982.  
  983. Syntax: int open(char *name, S16 kb=32);
  984.  
  985.  
  986.   // Example:
  987.   // Opening the existing database 'demo.dbf' with 40 kB for buffers.
  988.  
  989.    #include "CSTBASE.H"
  990.    void main(void)
  991.    {
  992.        TBASE db;
  993.        db.open("demo.dbf",40);
  994.    }
  995.  
  996.  
  997.  
  998. 10.5 Closing
  999.  
  1000. Closing the database involves writing all the buffered data back to disk
  1001. and freeing all allocated memory. The close() function is intended for
  1002. this purpose. If the close() function is not explicitly called in the
  1003. application, the class destructor will call it.
  1004.  
  1005. Because there can be a long interval between the last time the
  1006. database is used and the moment where the destructor is reached, it
  1007. still makes sense to call the close() function 'by hand'.
  1008.  
  1009. Syntax: int close(void);
  1010.  
  1011.  
  1012. //    Example:
  1013.  
  1014.     #include "CSTBASE.H"
  1015.     void main(void)
  1016.     {
  1017.        TBASE db;
  1018.        db.open("demo.dbf",40);
  1019.        db.close();
  1020.     }
  1021.  
  1022.  
  1023.  
  1024. 10.6 Appending Records
  1025.  
  1026. A special function is needed to add a record to a database: the
  1027. append_rec() function.
  1028. Note: The write_rec() can only overwrite an already existing record.
  1029.  
  1030. Syntax: long append_rec(void *data);
  1031.         'data' is a pointer to a record.
  1032.  
  1033. Syntax: long append_rec(void);
  1034.         This function can be used to add a record to the
  1035.         database without instantly filling it with a record. For
  1036.         the time being, this record will contain 'garbage'.
  1037.  
  1038.     // Example:
  1039.  
  1040.     #include "CSTBASE.H"
  1041.     void main(void)
  1042.     {
  1043.        typedef struct
  1044.        {
  1045.       char name[20];
  1046.       char street[40];
  1047.       char city[25];
  1048.        } record;
  1049.  
  1050.        TBASE db;
  1051.        record rec;
  1052.  
  1053.        db.define("demo.dbf",sizeof(record));   //Create new database
  1054.  
  1055.        db.open("demo.dbf",40);
  1056.  
  1057.        strcpy(rec.name,"J.Q. Querlis ");
  1058.        strcpy(rec.street,"Avenue 120");
  1059.        strcpy(rec.city,"Bombay");
  1060.  
  1061.        db.append_rec(&rec);       // The database now contains 1 record.
  1062.        db.close();
  1063.    }
  1064.  
  1065.  
  1066.  
  1067. 10.7 Deleting Records
  1068.  
  1069. Deleting a record cannot be accomplished instantaneously. A 'delete
  1070. bit' is used to distinguish deleted records.
  1071.  
  1072. Deleting a record by setting the 'delete bit' doesn't alter much. E.g.
  1073. record 9 remains record 9 if you delete record 8.
  1074. The function 'is_delet()' has to be called to detect whether-or-not a
  1075. record is 'deleted'.
  1076.  
  1077. The 'pack()' function can be used to physically remove all the deleted
  1078. records from the file.
  1079.  
  1080. int is_delet(long r);
  1081.         Returns 0 if the record 'r' is not deleted, and 1
  1082.         otherwise.
  1083.  
  1084. void delet(long r);
  1085.         Sets the delete bit for record 'r'.
  1086.  
  1087. void undelet(long r );
  1088.         Resets the delete bit for record 'r'.
  1089.  
  1090. void pack(void);
  1091.         Removes all the records with the delete bit set from
  1092.         the database. This is done without the use of
  1093.         temporary files.
  1094.  
  1095.  
  1096. 10.8 Advanced Topics
  1097.  
  1098. The next paragraph can be skipped by first-time readers.
  1099.  
  1100. 10.8.1 Page Utilization
  1101. The TBASE class does its IO in pages of 2 kB. It fits an integer number
  1102. of records on these pages. This approach can lead to a large chunk of
  1103. unused space on the pages, particularly if you are using large records.
  1104. On average the slack will be a half record, but if you have a record of
  1105. 1100 bytes almost 1 kB will be wasted!
  1106.  
  1107. Solution:
  1108.     This waste of disk space can be avoided by using pages which
  1109.     have the same size as the record. This means that the pages will
  1110.     no longer be aligned with the sectors of your harddisk!
  1111.  
  1112. The function to accomplish this is:  smallest_page().
  1113.  
  1114. void smallest_page(void);
  1115.         The function has to be called before the define()
  1116.         function. Because this changes the entire layout of
  1117.         the database file, this cannot be altered once the
  1118.         database is created.
  1119.  
  1120.  
  1121.     // Example:
  1122.  
  1123.     #include "CSTBASE.H"
  1124.  
  1125.     void main(void)
  1126.     {
  1127.  
  1128.        typedef struct
  1129.        {
  1130.       char name[20];
  1131.       char street[40];
  1132.       char city[25];
  1133.        } record;
  1134.  
  1135.        TBASE db;
  1136.  
  1137.        db.smallest_page();           //Before the define!
  1138.  
  1139.        db.define("demo.dbf",sizeof(record));
  1140.  
  1141.    }
  1142.  
  1143.  
  1144.  
  1145. 10.8.2 Locating Records
  1146. In the examples given so far, a record is first read into a local variable
  1147. and, after being altered, written back to disk. It seems there is room for
  1148. improvement here. After the record is copied into the local variable it is
  1149. in memory TWICE, once in the variable and another time in the
  1150. database buffers.
  1151.  
  1152. If you know what you are doing, a significant performance increase
  1153. can be gained from obtaining a pointer directly into the buffer system.
  1154.  
  1155. The 'locate_rec()' function does just that. When you are working in the
  1156. database buffers through a pointer, there is no way the buffer system
  1157. can tell if you are altering anything. Therefore, it's the programmers'
  1158. responsibility to indicate whether or not modifications are going to take
  1159. place.
  1160.  
  1161. char *locate_rec(long rec);
  1162.         This function returns a pointer to record 'rec'. It
  1163.         assumes that no alterations are going to take place.
  1164.         This means that the buffer is not written back to disk!
  1165.  
  1166. char *locate_rec_d(long rec);
  1167.         The additional '_d' stands for Dirty buffer. The
  1168.         function returns a pointer to record 'rec'. It is
  1169.         assumed alterations ARE going to take place. The
  1170.         buffer is therefore written back to disk when space is
  1171.         needed to store another page.
  1172.  
  1173.  
  1174. IMPORTANT!!
  1175. The locate functions return a pointer directly into the buffer
  1176. system. Nothing less and nothing more. Any member function
  1177. of the same class instance which MAY cause disk IO, can
  1178. therefore alter the contents of the buffers, making your pointer 'point' to
  1179. an entirely different record! When using these functions, it is highly
  1180. advisable to do all the reading or writing to the record before calling
  1181. any other TBASE member function.
  1182. Special care should be taken in using the 'background()' function.
  1183.  
  1184. If you are not sure you fully understand this, don't use the locate
  1185. functions.
  1186.  
  1187.  
  1188.  
  1189.  
  1190.  
  1191.     // Example, of the locate_ function.
  1192.  
  1193.     #include "CSTBASE.H"
  1194.  
  1195.     void main(void)
  1196.     {
  1197.  
  1198.        typedef struct
  1199.        {
  1200.       char name[20];
  1201.       int age;
  1202.        } record;
  1203.  
  1204.        TBASE db;
  1205.        record *rec;
  1206.  
  1207.        db.define("demo.dbf",sizeof(record));
  1208.        db.open("demo.dbf");                    // Use default 32 kB for buffers.
  1209.  
  1210.        for(int i=1;i<=12;i++) db.append_rec(); // Append 12 records.
  1211.  
  1212.        rec=(record *)db.locate_rec_d(7);       // Obtain pointer to record 7.
  1213.                    // '_d' because we will 'write'.
  1214.  
  1215.        rec->age=34;           // That's all it takes to make an
  1216.                    // alteration. No need for a
  1217.                    // 'write' function.
  1218.        db.close();           // Not strictly necessary.
  1219.  
  1220.    }
  1221.  
  1222.  
  1223.  
  1224. 10.9 Miscellaneous functions
  1225.  
  1226. long numrec(void);
  1227.         Returns the number of records currently in the
  1228.         database.
  1229.  
  1230. U16 lengthrec(void);
  1231.         The size of the record in bytes.
  1232.  
  1233. 10.10 Functions in alphabetical order.
  1234.  
  1235. Function prototypes are in 'cstbase.h'.
  1236.  
  1237.  
  1238. S32 append_rec(void *data);
  1239.         Append a record to the database. The newly created
  1240.         record is filled with the data from buffer 'data'. The
  1241.         function returns the number of the new record (which
  1242.         is equal to the number of records in the database).
  1243. S32 append_rec(void);
  1244.         Same as the previous function, only this time the new
  1245.         record is filled with binary zero's.
  1246. int close(void);    Closes the database. If the database is already
  1247.             closed, nothing happens. TRUE is returned on
  1248.             success, FALSE otherwise.
  1249. int define(char *name,U16  reclen);
  1250.         Creates a TBASE file named 'name'. The parameter
  1251.         'reclen' indicates the size of the records. TRUE is
  1252.         returned on success, FALSE otherwise.
  1253. void delet(S32    rec);
  1254.         Sets the delete bit of record 'rec'.
  1255. int empty(void);    Removes all the records from the database.
  1256.             Afterwards there will be zero records left, but the
  1257.             database will still be open. TRUE is returned on
  1258.             success, FALSE otherwise.
  1259. int is_delet(S32  rec);
  1260.         Returns the value of the delete bit of record 'rec'.
  1261.         TRUE means the delete bit is set, FALSE means the
  1262.         bit is not set.
  1263. U16 lengthrec(void);
  1264.         Returns the length of a record. Because TBASE
  1265.         works with fixed length records, this value is the
  1266.         same for all records. It's the same value used in the
  1267.         call to define().
  1268. char *locate_rec(S32  rec);
  1269. char *locate_rec_d(S32    rec);
  1270.         Functions to return a pointer to record 'rec' directly
  1271.         into the buffer system. Please read the paragraph
  1272.         about this topic before using these functions.
  1273. S32 numrec(void);
  1274.         Returns the number of records currently in the
  1275.         database. Whether or not a record is marked for
  1276.         deletion makes no difference.
  1277. int open(char *name,S16 kb=32);
  1278.         Opens the existing database 'name' while using 'kb'
  1279.         Kb ram for buffering. TRUE is returned on success,
  1280.         FALSE otherwise.
  1281. int open(void);     Returns TRUE if the database is open, FALSE
  1282.             otherwise.
  1283. int pack(void); Removes all the records with the delete bit set from
  1284.         the database. This is doen without the use of
  1285.         temporary files. TRUE is returned on success, FALSE
  1286.         otherwise.
  1287. void read_rec(S32 rec, void *buff);
  1288.         Copies the contents of record 'rec' into buffer 'buff'.
  1289. int save(void); Writes all buffered data back to disk. The database
  1290.         header block is also updated. The database remains
  1291.         open. TRUE is returned on success, FALSE
  1292.         otherwise.
  1293. void set_delet(S32  rec,int ToF);
  1294.         Changes the value of the delet bit of record 'rec'. If
  1295.         'ToF' is TRUE, the delete bit is set, otherwise it is
  1296.         reset.
  1297. void smallest_page(void);
  1298.         Set the page size to its smallest possible value. That
  1299.         is, a page will have the same size as a record. This
  1300.         means pages will no longer be alligned with the
  1301.         harddisk sectors. The function has to be called before
  1302.         the define() function. It changes the entire layout of
  1303.         the database file so it cannot be changed once the
  1304.         file is created.
  1305. void undelet(S32  rec);
  1306.         Resets the delete bit of record 'rec'.
  1307. void write_rec(S32 rec, void *buff);
  1308.         Overwrites the contents of record 'rec' the data from
  1309.         buffer 'buff'. Record 'rec' needs to exist, the function
  1310.         connot be used to append a record.
  1311.  
  1312.  
  1313.                 11 BTREE-class
  1314.  
  1315.  
  1316. 11.1 Introduction
  1317.  
  1318. A btree is a system, developed several decades ago, to store data in
  1319. some predetermined order. The btree is capable of maintaining this
  1320. order even under insertions and deletions.
  1321. It is possible to use btrees for data in ram, but they were designed (and
  1322. so optimized) to work with data on disk. Btrees are capable of locating,
  1323. inserting or deleting a specific record with only a few disk-IOs, even
  1324. when they have become very big.
  1325.  
  1326. Of course there is a price to be payed for this: the disk space occupied
  1327. by the btree is not fully utilized. Worst case, only 50% of the space is
  1328. used. Fortunate, in the average case 75% is used.
  1329.  
  1330. Btrees are convenient for indexes on a database. Of a record in the
  1331. main database, the key field and the corresponding record number are
  1332. stored together in the btree.
  1333. When a certain record is needed, the btree is capable of quickly
  1334. (without much disk IO) locating the required key value because the
  1335. btree keeps the key values sorted. When the key field is located in the
  1336. btree, it is instantly clear which record from the main database has to
  1337. be read from disk.
  1338.  
  1339. There are several 'flavours' of btrees. The one implemented in this
  1340. library is known as a 'btree+'.
  1341.  
  1342.  
  1343. 11.2 BTREEx Classes
  1344.  
  1345. Unfortunate, it's a little cumbersome to use one BTREE class for every
  1346. type of data. Therefore, there are several minor variations on the main
  1347. BTREE class to account for the different variable types supported by C.
  1348. Each type has its own class.
  1349.  
  1350. Classes:
  1351.     BTREEb  For binary data.
  1352.     BTREEi  For integers.
  1353.     BTREEl  For longs.
  1354.     BTREEc  For characters.
  1355.     BTREEf  For floats.
  1356.     BTREEd  For doubles.
  1357.     BTREEa  For ASCII data. (Strings)
  1358.  
  1359. All these classes are derived from the BTREE class. Mainly, they differ
  1360. only in one function. This is the function needed to compare keys. You
  1361. can easily define a new BTREE class for new type of variable. The only
  1362. thing to do is define a int t_key(void *a,void *b) function which returns:
  1363.  
  1364.     >0    if  a>b
  1365.      0    if  a==b
  1366.     <0    if  a<b
  1367.  
  1368. with 'a' and 'b' pointers to the new type of variables.
  1369.  
  1370.  
  1371. Example:
  1372. Say, you have your data stored in a C structure which
  1373. you want to kept sorted on one of its fields.
  1374.  
  1375. Something like:
  1376.  
  1377.       typedef struct
  1378.       {
  1379.      char name[20];
  1380.      int  number;
  1381.       }
  1382.  
  1383. Which you want to have sorted on the 'number' field.
  1384.  
  1385. class BTREEnew: public BTREE
  1386. {
  1387.  
  1388.     virtual int t_key(void *a,void *b)
  1389.     {
  1390.        return ((record *)a)->number-((record *)b)->number;
  1391.     }
  1392.     virtual int class_ID(void)    { return -100; }
  1393.  };
  1394.  
  1395.  
  1396. That's all!
  1397. The value '-100' in the class_ID() function is not all that important. Its
  1398. purpose is to give other library functions the opportunity to distinguish
  1399. between the classes. The value just has to be different from any value
  1400. the other classes have. This can easily be accomplished by choosing a
  1401. negative number.
  1402.  
  1403.  
  1404. 11.3 Multiple Keys
  1405.  
  1406. Because of its nature you would expect a 'key' to appear only once in a
  1407. btree. However, on many occasions it turns out there is a need for
  1408. storing the same key more then once, but with a different data part.
  1409. E.g. this happens when you use a btree as an index on a database and
  1410. in  the field  you are indexing a certain value appears more then once.
  1411. In that case, you want to store the key value several times but with a
  1412. different data part, namely the record number in the database.
  1413.  
  1414. By default a key value can appear only once in the btree. If you try to
  1415. insert a second entry with the same key value, it will simply replace the
  1416. existing one. The option 'multiple_keys()' can be set  to alter all that.
  1417.  
  1418. Syntax: void multiple_keys(int    YesNo);
  1419.     void multiple_keys_YES(void);
  1420.     void multiple_keys_NO(void);
  1421.  
  1422.  
  1423. When the function 'multiple_keys()' is called with the argument set to
  1424. TRUE, the btree will store a key value more then once.
  1425.  
  1426. It is important to realize that the btree only keeps the key
  1427. values sorted, NOT the data values. This means that when
  1428. you are searching for a particular key/data value, the btree is
  1429. capable of quickly locating the required key but has to find the correct
  1430. data value by sequentially traversing all the inserted data belonging to
  1431. that particular key.
  1432.  
  1433. Btrees are intended to give quick access to key values by keeping
  1434. them sorted, this does not apply to data values. Expecting anything
  1435. else is misusing the btree. If you want quick access to a large number
  1436. of different data values, all belonging to the same key, you need a
  1437. different approach. The best thing to do is to construct a new btree and
  1438. use a key which is a concatenation of the original key and the original
  1439. data part.
  1440.  
  1441. Setting the multiple_keys option has to take place before the 'define'.
  1442.  
  1443.  
  1444. // Example
  1445.  
  1446. #include "csbtree.h"
  1447.  
  1448. void main(void)
  1449. {
  1450.  
  1451.     typedef struct
  1452.     {
  1453.     char name[20];
  1454.     int  age;
  1455.     } record;
  1456.  
  1457.     BTREE bt;
  1458.  
  1459.     bt.multiple_keys_YES(); // Must be called before 'define'
  1460.     bt.define("btree.dat",sizeof(record),sizeof(long));
  1461.  
  1462.     // By now a btree 'btree.dat' is created in the current working
  1463.     // directory with the multiple-keys option switched on.
  1464.  
  1465. }
  1466.  
  1467.  
  1468.  
  1469.  
  1470. 11.4 Current Pointer
  1471.  
  1472. Contrary to TBASE, the btree class does use a 'current' pointer. When
  1473. using btrees, the need to obtain the next (or previous) entry arises so
  1474. often it's inevitable.
  1475.  
  1476. The btree class spends as little time as possible on maintaining this
  1477. current  pointer. Therefore you should assume it is NOT set, unless you
  1478. have strong reasons to believe otherwise.
  1479.  
  1480. A limited set of functions can be used to set the current pointer. After
  1481. that, the 'next()' and the 'previous()' functions can be used to move to
  1482. the next resp. the previous entry.
  1483. When these functions 'fail', which can be noticed from their return
  1484. value,    you should assume the current pointer is not set (any more).
  1485.  
  1486. The next functions can be used to set the current pointer:
  1487. - all the search functions.
  1488.     E.g.  search_gt(),    find() etc.
  1489. - all the min() and max() functions.
  1490.     E.g. max_key(), min() etc.
  1491. - the insert() function.
  1492.  
  1493. The current pointer can be moved back and forth with the next() and
  1494. previous() functions.
  1495.  
  1496. Once the current pointer is set, the 'current()' functions can be used to
  1497. obtain the key value and/or the data part.
  1498.  
  1499. Any other function can, and probably will, render the value
  1500. of the current pointer undefined!
  1501.  
  1502.  
  1503.  
  1504. // Example
  1505. // The next example displays the contents of a btree with
  1506. // 'strings' as key fields.
  1507. // It assumes that the btree 'demo.dbf' exists and that the
  1508. // key fields are less then 100 bytes.
  1509.  
  1510. #include "iostream.h"
  1511. #include "csbtree.h"
  1512.  
  1513. void main(void)
  1514. {
  1515.      char  buffer[100];
  1516.      BTREEa bt;
  1517.  
  1518.      bt.open("demo.dbf",250);  // Does not set the current pointer.
  1519.  
  1520.               // Make the first entry the 'current'.
  1521.      if(bt.min())     // This returns FALSE only if the btree is empty.
  1522.      do
  1523.      {
  1524.      bt.current_key(buffer);  // Read the 'current' key value.
  1525.       cout<<buffer<<endl;       // Display it.
  1526.       } while(bt.next());       // Move the current pointer 1 position.
  1527.  
  1528.       bt.close();
  1529. }
  1530.  
  1531.  
  1532.  
  1533. 11.5 Using Btrees
  1534.  
  1535. The next paragraph will try to sort the public memeber functions
  1536. according to their purpose.
  1537.  
  1538. 11.5.1 Creating
  1539.  
  1540.     void multiple_keys_YES(void);
  1541.     void define(char *name,int key_length, int data_length);
  1542.  
  1543. 11.5.2 Opening
  1544.  
  1545.     int open(char *name, int kb_buffer);
  1546.  
  1547. 11.5.3 Inserting
  1548.  
  1549.     void insert(void *key,void *data);
  1550.  
  1551. 11.5.4 Searching
  1552.  
  1553.     int   search(void *key,void *Data);
  1554.     int   search_gt(void *key,void *Key,void *Data);
  1555.     int   search_ge(void *key,void *Key,void *Data);
  1556.     int   search_lt(void *key,void *Key,void *Data);
  1557.     int   search_le(void *key,void *Key,void *Data);
  1558.     int   search_dat_..(void *key,void *Data);
  1559.     int   search_key_..(void *key,void *Key);
  1560.     int   find(void *key,void *data);
  1561.     int   find(void *key);
  1562.     int   max(void *Key,void *Data);
  1563.     int   min(void *Key,void *Data);
  1564.  
  1565. 11.5.5 Current
  1566.  
  1567.     int   current(void *Key,void *Data);
  1568.     int   current_key(void *Key);
  1569.     int   current_dat(void *Data);
  1570.  
  1571. 11.5.6 Deleting
  1572.  
  1573.     int   delet(void *delete_key);
  1574.     int   delet(void *delete_key,void *data_value);
  1575.  
  1576. 11.5.7 Closing
  1577.  
  1578.     void  close(void);
  1579. 11.6 Functions in alphabetical order.
  1580.  
  1581. The function prototypes are in "CSBTREE.H".
  1582.  
  1583. void  close(void);
  1584.         Closes the btree after use. All buffers are flushed and
  1585.         all the allocated memory is freed. This function is also
  1586.         called by the class destructor if needed.
  1587. int   current(void *Key,void *Data);
  1588. int   current_key(void *Key);
  1589. int   current_dat(void *Data);
  1590.         Returns the key and/or data part of the entry the
  1591.         current pointer is pointing at.
  1592.         Parameters:
  1593.         Key Pointer to the buffer to which the key value
  1594.             has to be copied.
  1595.         Data    Pointer to the buffer to which the data part
  1596.             has to be copied.
  1597.         If the current pointer has not been set, the functions
  1598.         return FALSE and no data is written into the buffers.
  1599.         If the current pointer is set, the functions return TRUE
  1600.         and the appropriate data is copied into the buffers.
  1601. void define(char *name, int key_length,int dat_length);
  1602.         This function is needed to initially create the file and
  1603.         properly setup all variables. This is only needed once,
  1604.         before the first call to open().
  1605.         Parameters:
  1606.         name        The filename which is going to be used.
  1607.         key_length  The number of bytes in the key. This
  1608.                 parameter is even needed when its
  1609.                 value is 'obvious' from the btree type.
  1610.         dat_length  The number of bytes in the data part.
  1611.  
  1612.     Example:
  1613.  
  1614.     If you want to use a btree as index on a string field
  1615.     in a database you will need:
  1616.     - a btree of type ASCII: BTREEa.
  1617.     - a key_length equal to the length of the string field
  1618.       in the database record.
  1619.     - a data part which is capable of holding the number
  1620.       of the record in the database. This will normally be
  1621.       a 'long'.
  1622.  
  1623.     #include "cstbase.h"
  1624.     #include "csbtree.h"
  1625.  
  1626.     void main(void)
  1627.     {
  1628.     typedef struct
  1629.     {
  1630.        char   name[30];
  1631.        float   income;
  1632.     }record;
  1633.  
  1634.     TBASE  db;
  1635.     BTREEa index;
  1636.  
  1637.     db.define("demo.dbf",sizeof(record));
  1638.     index.define("demo.ndx",30,sizeof(long));
  1639.  
  1640.     }
  1641.  
  1642.  
  1643.  
  1644. int   delet(void *delete_key);
  1645.         Searches for key 'delete_key' and, if present,
  1646.         removes it from the btree. If the option multiple_keys
  1647.         is set to 'yes' there can be more then one entry with
  1648.         the required key. Under that circumstances, all these
  1649.         entries will be removed. The function delet() can also
  1650.         accept a parameter with the value of the data part.
  1651.         That function should be used for deleting when
  1652.         multiple keys are used.
  1653.         The function returns TRUE is something is deleted,
  1654.         FALSE otherwise.
  1655. int   delet(void *delete_key,void *data_value);
  1656.         The same as the previous delete function but this
  1657.         time the value of the data part is also specified. Only
  1658.         the entry which matches both the key and the data
  1659.         part is removed from the btree.
  1660. void  empty(void);
  1661.         Removes all the entries in the btree. Upon return, the
  1662.         btree will contain zero keys.
  1663.         The btree needs to be open, and will remain open
  1664.         afterwards.
  1665. int   find(void *key,void *data);
  1666. int   find(void *key);
  1667.         These functions 'test' if a certain key value is present
  1668.         in the btree. When a btree is used with multiple keys,
  1669.         it can be necessary to specify the data part to
  1670.         uniquely identify an entry.
  1671.         TRUE is returned when the required entry is found,
  1672.         FALSE otherwise.
  1673. void  insert(void *key,void *data);
  1674.         Inserts a new entry in the btree. 'key' is a pointer to
  1675.         the key field and 'data' is a pointer to the data part.
  1676.  
  1677.  
  1678. //    Example:
  1679.  
  1680.     void main(void)
  1681.     {
  1682.  
  1683.     typedef struct
  1684.     {
  1685.        char   name[30];
  1686.        float   income;
  1687.     }record;
  1688.  
  1689.     TBASE  db;
  1690.     BTREEa index;
  1691.  
  1692.     db.define("demo.dbf",sizeof(record));        //Creating.
  1693.     index.define("demo.ndx",30,sizeof(long));    //Creating.
  1694.  
  1695.     db.open("demo.dbf",30);         // Opening the database with 30 Kb buffers
  1696.     index.open("demo.ndx",80);      // Opening the index with 80 Kb buffers.
  1697.  
  1698.     record rec;
  1699.  
  1700.     strcpy(rec.name,"John Wayne");
  1701.     rec.income=7000;        // Filling the record.
  1702.  
  1703.     long recnr=db.append_rec(&rec); // Insert in the database.
  1704.     index.insert(rec.name,&recnr);    // Update the index.
  1705.  
  1706.     db.close();            // Close the database.
  1707.     index.close();            // Close the index.
  1708.  
  1709.     }
  1710.  
  1711.  
  1712. int   max(void *Key,void *Data);
  1713. int   max_dat(void *Data);
  1714. int   max_key(void *Key);
  1715. int   max(void);
  1716.         These functions return the last (highest) entry in the
  1717.         btree. The parameters 'Key' and 'Data'  have to be
  1718.         pointers to respectively a buffer for the key part and a
  1719.         buffer for the data part. These buffers will be filled
  1720.         with the appropriate data upon function return.
  1721.         The functions max_dat() and max_key() can be used
  1722.         when only one of the two parts is required.
  1723.         TRUE is returned on success, FALSE otherwise.
  1724. int   min(void *Key,void *Data);
  1725. int   min_dat(void *Data);
  1726. int   min_key(void *Key);
  1727. int   min(void);
  1728.         These functions return the first (lowest) entry in the
  1729.         btree. The parameters 'Key' and 'Data'  have to be
  1730.         pointers to respectively a buffer for the key part and a
  1731.         buffer for the data part. These buffers will be filled
  1732.         with the appropriate data upon function return.
  1733.         The functions min_dat() and min_key() can be used
  1734.         when just one of the two parts is required.
  1735.         TRUE is returned on success, FALSE otherwise.
  1736. void  multiple_keys(int TrueOrFalse);
  1737.         With this function the use of multiple keys is
  1738.         controlled. For more information about multiple keys
  1739.         please read the paragraph about the subject.
  1740.         Multiple_keys(TRUE) will allow for multiple keys.
  1741.         Multiple_keys(FALSE) will not allow for multiple keys.
  1742.         Important:
  1743.         This function has to be called before the define()
  1744.         function is invoked. It is not possible to alter the
  1745.         setting of the multiple key parameter later on.
  1746. int   multiple_keys_YES(void);
  1747.         Same as multiple_keys(TRUE);
  1748. int   multiple_keys_NO(void);
  1749.         Same as multiple_keys(FALSE);
  1750. int   multiple_keys(void);
  1751.         This function returns TRUE if multiple keys is set to
  1752.         'YES' and FALSE otherwise.
  1753. int   next(int n);
  1754. int   next_key(int n,void *Key);
  1755. int   next_dat(int n,void *Data);
  1756. int   next(int n,void *Key,void *Data);
  1757.         A set of functions to move the current pointer closer
  1758.         to the 'end' of the btree.
  1759.         Apart from that, they are similar to the prev() funtions.
  1760.         For more information, please see over there.
  1761. int   next(void);
  1762.         Same as next(1); but more efficient.
  1763. long  numkey(void);
  1764.         This function returns the number of entries which
  1765.         exists in the btree.
  1766. int   open(char *name, int kb_buff);
  1767.         Opens an existing btree 'name'. The parameter
  1768.         'kb_buff' indicates how many Kb ram has to be used
  1769.         for buffering.
  1770.         The function returns TRUE on success, FALSE
  1771.         otherwise.
  1772.  
  1773.     //Example:
  1774.  
  1775.     #include "csbtree.h"
  1776.  
  1777.     void main(void)
  1778.     {
  1779.  
  1780.        BTREEa index;
  1781.        index.open("demo.ndx",100);
  1782.  
  1783.     }
  1784.  
  1785.         This will open the btree 'demo.ndx' and will, at most,
  1786.         use 100 Kb ram for buffering.
  1787.         NOTE:    read the chapter about buffering, before
  1788.             using really large amounts of buffers.
  1789. void  pack(void);
  1790.         A function which optimizes disk usage. Due to many
  1791.         insertions and deletions it is possible for blocks with
  1792.         zero keys to emerge. There are no pointers to these
  1793.         blocks but they will still be part of the btree because
  1794.         they can not be removed unless they are the last
  1795.         block in the file. These blocks will be used as soon
  1796.         as the need for a new block arises.
  1797.         The pack function will remove these empty blocks
  1798.         and rearrange all the keys. This is done by writing all
  1799.         the data to a temporary file and reload the btree.
  1800.         Afterwards the btree will be (close to) 100% full.
  1801. int   prev(void);
  1802. int   prev(int n);
  1803. int   prev_key(int n,void *Key);
  1804. int   prev_dat(int n,void *Data);
  1805. int   prev(int n,void *Key,void *Data);
  1806.         A set of functions to move the current pointer closer
  1807.         to the 'beginning' of the btree.
  1808.         Parameters:
  1809.         n    The number of entries the current pointer
  1810.             needs to be moved.
  1811.         Key A pointer to the buffer which is going to be
  1812.             filled with the value of the key field.
  1813.         Data    A pointer to the buffer which is going to be
  1814.             filled with the value of the data part.
  1815.         When the current pointer is NOT moved, the key and
  1816.         data buffers will not be filled. Otherwise they will be
  1817.         filled with the values of the entry to which the current
  1818.         pointer is moved.
  1819.         The key field, the data field, or both can be obtained
  1820.         by selecting the appropriate function.
  1821.         The prev(void) function is a much more efficient
  1822.         version of the prev(1) function.
  1823.         Important:
  1824.         This current pointer needs to be set first. Please,
  1825.         read the praragraph about the 'current pointer' for
  1826.         more information.
  1827.         When one of the prev() functions is called while the
  1828.         current pointer is not set, the function will return 0.
  1829.         This current pointer can not be moved before the
  1830.         beginning of the btree. Therefore the number of
  1831.         positions moved can differ from the number
  1832.         requested.
  1833.         The return value is the number of positions the
  1834.         current pointer has actually moved.
  1835. int   search(void *key,void *Data);
  1836.         Searches for 'key' and fills buffer 'Data' with the
  1837.         corresponding data part if 'key' is found.
  1838.         The function returns TRUE if found, FALSE
  1839.         otherwise.
  1840. int   search_gt(void *key,void *Key,void *Data);
  1841. int   search_ge(void *key,void *Key,void *Data);
  1842. int   search_lt(void *key,void *Key,void *Data);
  1843. int   search_le(void *key,void *Key,void *Data);
  1844.         The purpose of this set of functions is to search for a
  1845.         key value next to a given value. The names of the
  1846.         output parameters start with a capital while the input
  1847.         parameters are all lower case.
  1848.         The suffix '_xx' has a meaning conform to the
  1849.         corresponding FORTRAN operators:
  1850.         gt: Greater Then    >
  1851.         ge: Greater Equal    >=
  1852.         lt: Less Then        <
  1853.         le: Less Equal        <=
  1854.         The functions return TRUE if such a key could be
  1855.         found, FALSE if not.
  1856.  
  1857.      Example:
  1858.      Assume the next table represents a btree.
  1859.  
  1860.      Entry      Key value    Data value
  1861.  
  1862.       1         Blue       123
  1863.       2         Green        45
  1864.       3         Red       678
  1865.  
  1866.        search_gt("Blue",Key,Data)
  1867.     Return value:    TRUE
  1868.     Key:        Green
  1869.     Data:         45
  1870.  
  1871.        search_ge("Blue",Key,Data)
  1872.     Return value:    TRUE
  1873.     Key:        Blue
  1874.     Data:        123
  1875.  
  1876.        search_lt("Blue",Key,Data)
  1877.     Return value:    FALSE
  1878.     Key:        undefined
  1879.     Data:        undefined
  1880.  
  1881.        search_ge("Orange",Key,Data)
  1882.     Return value:    TRUE
  1883.     Key:        Red
  1884.     Data:        678
  1885.  
  1886.  
  1887. int   search_dat_..(void *key,void *Data);
  1888. int   search_key_..(void *key,void *Key);
  1889.         The previous described functions return both the key
  1890.         value and the data value.
  1891.         In some cases this will be a waste of memory,
  1892.         therefore there are two similar sets of functions,
  1893.         which either return the found key value or the data
  1894.         part.
  1895.         search_dat_..() returns only the found data value.
  1896.         search_key_..() returns only the found key value.
  1897.  
  1898.     Example:
  1899.  
  1900.     With the same btree as in the previous example
  1901.  
  1902.  
  1903.        search_dat_gt("Blue",Data)
  1904.     Return value:    TRUE
  1905.     Data:        45
  1906.  
  1907.        search_key_ge("Blue",Key)
  1908.     Return value:    TRUE
  1909.     Key:         Blue
  1910.  
  1911.  
  1912. int   skip(int n);
  1913. int   skip(int n,void *Key,void *Data);
  1914. int   skip_key(int n,void *Key);
  1915. int   skip_dat(int n,void *Dat);
  1916.         A set of functions to move the current pointer. These
  1917.         functions are front ends for the next() and prev()
  1918.         functions. E.g. this is how the skip_key() function is
  1919.         implemented:
  1920.  
  1921.  
  1922.         int skip_key(int n,void *Key)
  1923.             {  if(n>0) return  next_key( n,Key);
  1924.                else    return -prev_key(-n,Key); }
  1925.  
  1926.  
  1927.         So, with these functions the argument 'n' may be
  1928.         positive or negative.
  1929.         With 'n' positive the current pointer is moved to the
  1930.         'end' of the btree. This is done by calling next(n).
  1931.         With 'n' negative the current pointer is moved to the
  1932.         'beginning' of the btree. This is done by calling
  1933.         -prev(-n).
  1934.         The return value can be either positive or negative
  1935.         depending on the value of 'n'. When 0 is returned, the
  1936.         current pointer has not been moved or was not set.
  1937.         See also the prev() functions for more information.
  1938. void  zap(void);
  1939.         Closes the btree (when needed) and re-establishes
  1940.         all defaults. In other words: the zap() function
  1941.         restores the status of the btree immediatly after the
  1942.         class constructor. Its purpose is to open (or create) a
  1943.         new btree, starting of with all the parameters set to
  1944.         their default values.
  1945.                   12 CSDBGEN
  1946.  
  1947.  
  1948. 12.1 Introduction
  1949.  
  1950. CSDBGEN is a program generator.
  1951.  
  1952. So far we have discussed the TBASE class which is capable of reading
  1953. and writing records and the BTREE class which can be used as an
  1954. index. CSDBGEN is needed to make a nice database out of this, which
  1955. is capable of manipulating fields, maintaining indexes and the alike.
  1956.  
  1957. It takes as input a 'definition file' which describes the fields and the
  1958. indexes. From this it produces the source for a new C++ class. Member
  1959. functions of this newly created class are used to access the fields.
  1960.  
  1961. CSDBGEN does not generate a user-interface.
  1962.  
  1963. There are several good reasons for using a program generator.
  1964. - The TBASE class can concentrate on manipulating records rather
  1965.     then fields. Because of that, it remains a universal and efficient
  1966.     way to do disk IO.
  1967. - With this approach it is easier to deal with field types that are not
  1968.     supported  by the C programming language, particularly dates.
  1969. - It is relatively easy for the program generator to convert to dBASE
  1970.     format because it has all the required knowledge at hand. Figuring
  1971.     out this conversion during runtime is a lot more complicated and
  1972.     will also make your executable larger because the knowledge to do
  1973.     the conversion is in the application instead of in the program
  1974.     generator.
  1975. - Or more in general: everything the program generator does, can be
  1976.     left out from the application, making the executable smaller.
  1977. - Without a program generator, the differences between the field types
  1978.     have to be dealt with runtime, perhaps even with every call
  1979.     accessing a field. Doing so, will inevitable result in some sort of an
  1980.     interpreter. Interpreters have two major drawbacks. First they are
  1981.     amazingly slow, and second they contain functions to handle every
  1982.     possible case. This means code is linked in for every known field
  1983.     type, even if it's not used.
  1984.  
  1985. 12.2 Overview
  1986.  
  1987. Using CSDBGEN starts of with creating a definition file. This file
  1988. describes the layout of a record, the indexes, the name of the new
  1989. class and the name of the files.
  1990.  
  1991. When this file is created, CSDBGEN is called with this filename as a
  1992. parameter. In return you will obtain the source for a brand new C++
  1993. class. This source is ready to compile, without the need for manual
  1994. editing.
  1995.  
  1996. This new class has public member functions for things like reading a
  1997. field, setting the active index, exporting to ASCII, exporting to dBASE,
  1998. reindexing, packing and so on.
  1999. These member functions are very easy to use because they take very
  2000. few, and often none, parameters. This is possible because a lot of the
  2001. information which is specific for the database is already in the source of
  2002. the functions.
  2003.  
  2004. The generated class controls one database and all the indexes that
  2005. come with it. If you need more then one database, as is to be
  2006. expected, you have to repeat this procedure for the other databases as
  2007. well.
  2008.  
  2009. CSDBGEN does not aid in building the user-interface.
  2010.  
  2011. An elaborate example is at the end of this chapter.
  2012.  
  2013. 12.3 Features
  2014.  
  2015. - Indexes with more then one reference to a record!
  2016.     This is an innovation! It makes it possible to locate a record by
  2017.     searching for a substring in the field, rather then the entire field.
  2018.     This topic is discussed in more detail in the paragraph 'tokenizing'.
  2019. - Conversion to-and-from ASCII.
  2020.     This is convenient for backups, conversions to other systems and
  2021.     also for making changes in the record layout.
  2022. - Export to dBASE compatible file format.
  2023.     CSDBGEN generates a function capable of writing out the contents
  2024.     of the database to a file which can be read by dBASE.
  2025. - Can manage very large databases.
  2026.     The design of the libraries has been keen on avoiding limitations.
  2027.     By result, databases up to 2 billion records are theoretically
  2028.     feasible.
  2029. - No overhead.
  2030.     Due to the use of a program generator, the overhead involved in
  2031.     accessing fields is next to none.
  2032. - Large buffers.
  2033.     This system is capable of effectively using large amounts of RAM
  2034.     for buffering.
  2035. - Fast.
  2036.     The precious two points, together with the efficient BTREEs
  2037.     guarantee a very fast database.
  2038.  
  2039.  
  2040. 12.4 Limitations
  2041.  
  2042. - No record locking.
  2043. - No multi-user support.
  2044.     This system was designed to be used in single user applications.
  2045.     Time being, there is no support for network/shared databases.
  2046.     Perhaps there will be in the future but if so, it will take the form of
  2047.     a new series of classes.
  2048.  
  2049.  
  2050. 12.5 Definition file
  2051.  
  2052. The information needed to generate the new class is obtained from a
  2053. 'definition file'. To get you started, the CSDBGEN utility is capable of
  2054. generating an example.
  2055.  
  2056.  
  2057. //example
  2058.  
  2059. c:\borlandc>csdbgen /example>example.def
  2060.  
  2061. Something like this will generate an example definition file 'example.def'.
  2062.  
  2063.  
  2064.  
  2065. To get acquainted, let's look what's in it.
  2066.  
  2067. Example definition file:
  2068.  
  2069.     class:  NAM
  2070.     record: NAM_record
  2071.     file:   demo
  2072.     field:  name    s   30    Y
  2073.     field:  city    s   20
  2074.     field:  birthday    d    Y
  2075.     field:  salary    f
  2076.  
  2077.  
  2078.  
  2079. Explanation:
  2080.  
  2081.     line 1: class:  NAM
  2082.     The program generator generates a class, which of course has
  2083.     to have a name. In this example 'NAM' .
  2084.  
  2085.     line 2: record: NAM_record
  2086.     As explained before, the database system uses a C structure
  2087.     as a record. The name of this structure is defined in the
  2088.     second line.
  2089.     In the generated header file the following (among others) will
  2090.     appear:
  2091.  
  2092.  
  2093.      #define NAME_LENGTH      30
  2094.      #define CITY_LENGTH      20
  2095.  
  2096.      typedef struct
  2097.      {
  2098.         char   _name[NAME_LENGTH+1];
  2099.         char   _city[CITY_LENGTH+1];
  2100.         long   __birthday;
  2101.         float  _salary;
  2102.      } NAM_record;
  2103.  
  2104.  
  2105.     line 3: file:   demo
  2106.     This line indicates the name of the files the database system
  2107.     is going to use. In this example three files will be used:
  2108.         - demo.dbf, the TBASE database file.
  2109.         - demo01.idx, the BTREE index file on field 'name'.
  2110.         - demo02.idx, the BTREE index file on field 'birthday'.
  2111.  
  2112.  
  2113.     line 4/7:
  2114.     Field definitions.
  2115.     The syntax for a field definition is:
  2116.     field: <field_name> <field_type> [length] [format] [index]
  2117.     With:
  2118.         field_name, the name of the field.
  2119.         field_type, the type of the field which can be:
  2120.         i:  integer
  2121.         l:  long
  2122.         f:  float
  2123.         F:  double
  2124.         c:  character
  2125.         s:  string
  2126.         length, only for strings.
  2127.         Indicates the number of characters the field needs to
  2128.         be able to store. One additional byte is reserved to
  2129.         store the null terminator.
  2130.         format, only for date fields.
  2131.         Please, see the documentation on DATE fields.
  2132.         To give a quick example: MDY4 means, Month, Day
  2133.         and 4 positions for the Year.
  2134.         index,
  2135.         'Y' means a normal index.
  2136.         'T' means a 'tokenized' index.
  2137.          Nothing means no index at all.
  2138.         See also the documentation on 'tokenizing' further on.
  2139.  
  2140. In the example:
  2141.  
  2142.     field:  name    s    30  Y
  2143.     A field 'name' of type string. 31 Bytes are reserved, 30 for the
  2144.     characters and 1 for the null terminator. An index is
  2145.     maintained for this field because of the additional 'Y'.
  2146.  
  2147.     field:  city    s    20
  2148.     A field 'city' of type string with a length of 20 characters. There
  2149.     is NO index on this field.
  2150.  
  2151.     field:  birthday    d   Y
  2152.     A field 'birthday' of type DATE. An index is placed on this field.
  2153.  
  2154.     field:  salary  f
  2155.     A field 'salary' of type float, without an index.
  2156.  
  2157.  
  2158. 12.6 Tokenizing
  2159.  
  2160. This is a new concept!
  2161.  
  2162. Let's look at an example to make things clear.
  2163.  
  2164. The demonstration database CSADDR, which comes with this package,
  2165. uses tokenizing on its 'name' field.
  2166.  
  2167. Let's say you have entered a record for the 'World Health Organization'.
  2168. And now, for the first time in your life, can locate this record by entering
  2169. 'health'. In fact, because CSADDR uses something called incremental
  2170. search, entering just 'hea' is probably sufficient to pop up the record.
  2171. It's important to know that this feature is not implemented by traversing
  2172. the entire database from the first record to the last, as is done by some
  2173. toy-applications.
  2174.  
  2175.  
  2176. 12.6.1 How does it work?
  2177.  
  2178. Traditionally, the index stores the entire field. In this example that would
  2179. mean 'World Health Organization' is stored in the index together with a
  2180. reference to the record number in the main database.
  2181. With tokenizing, the index will store 3 entries, namely 'World', 'Health'
  2182. and 'Organization'. This approach means that there will be a lot more
  2183. entries in the btree then there are records in TBASE.
  2184.  
  2185. In other words, an index is maintained on every suitable substring,
  2186. rather then the entire field.
  2187.  
  2188. To save disk space, the length of the key field in the BTREE
  2189. is only half of the field length in the main database.
  2190.  
  2191.  
  2192. 12.7 When is a substring indexed?
  2193.  
  2194. First of all: tokenizing only applies for string fields. E.g. 'Tokenizing' a
  2195. float field seams pointless.
  2196.  
  2197. Whether or not a substring is put in the index is controlled by two
  2198. things:
  2199. - the way it is separated from the rest of the field.
  2200. - the length of the substring.
  2201.  
  2202. CSDBGEN generates a function 'tokenize'. This function contains a
  2203. string 'delim' and a constant 'min_len'.
  2204.  
  2205.  
  2206. // A part of the 'tokenize' function.
  2207.  
  2208.     char delim[]="\t,() ";  // Token delimiters
  2209.     const min_len=4;        // Minimum length for a token to be indexed
  2210.  
  2211.  
  2212.  
  2213. The tokenize function separates the field into substrings according to
  2214. the characters in the 'delim' array. Notice that the '.' is not a delimiter.
  2215. This is to prevent abbreviations from being split up.
  2216. A substring has to be at least four bytes long to appear in an index.
  2217. This is not too long for most cases but it means that three letter
  2218. abbreviations like 'IRS' are not indexed.
  2219.  
  2220. Of course you can alter these two variables when needed.
  2221.  
  2222.  
  2223. Example definition file:
  2224.  
  2225.   class:    NAM
  2226.   record:   NAM_record
  2227.   file:     demo
  2228.   field:    name    s   30    T
  2229.   field:    city    s   20
  2230.   field:    birthday    d
  2231.   field:    salary    f
  2232.  
  2233.  
  2234. Notice the 'T' behind the 'name' field. This is short for 'tokenize'. The
  2235. generated class will maintain an index for the name field with
  2236. references for every suitable substring.
  2237.  
  2238. 12.8 Export to dBASE
  2239.  
  2240. The program generator also produces a  member function:
  2241.  
  2242.     int to_DBASE(char *filename);
  2243.  
  2244. When called, this function produces a file 'filename' which can be read
  2245. by dBASE. Index files are NOT written.
  2246. At this moment there is no corresponding function to do the conversion
  2247. the other way round.
  2248.  
  2249.  
  2250. 12.9 Exporting/Importing to/from ASCII
  2251.  
  2252.     int export(char *filename);
  2253.  
  2254. This writes out the contents of the database to an ASCII file 'filename'.
  2255. That file will also contain information about the fields. In this way the
  2256. import() function knows how to process this data, even after changes in
  2257. the record layout.
  2258.  
  2259.     int import(char *filename);
  2260.  
  2261. This member function reads the ASCII file 'filename' and appends its
  2262. data to the current database. It is meant to be used in conjunction with
  2263. the export() function. The export function starts of with writing the entire
  2264. definition file. The import function uses this information to skip fields
  2265. which are not in the database and to read fields in the right order. Only
  2266. fields which are also in the current database are read, the others are
  2267. ignored. This mechanism can be used to make changes in the record
  2268. layout.
  2269.  
  2270.  
  2271. 12.10 Starting a new database
  2272.  
  2273. A member function
  2274.  
  2275.     void define(void);
  2276.  
  2277. is available to create a new database. If the database already exists, it
  2278. is overwritten!
  2279.  
  2280.  
  2281. 12.11 Opening a database
  2282.  
  2283. The member function
  2284.  
  2285.     void open(void);
  2286.  
  2287. opens an existing database. To avoid errors, a blank record is inserted
  2288. when an empty database is opened.
  2289. Index files are automatically rebuilt if they don't exist.
  2290.  
  2291.  
  2292. 12.12 Current Record
  2293.  
  2294. At any moment there is always a record the 'current record'. The
  2295. functions to read and write fields all work with this current record.
  2296.  
  2297. - After opening, the first record becomes the current record.
  2298. - The go_to(), skip(), top(), bottom() and the search()  functions can be
  2299.     used to make another record 'current'.
  2300.  
  2301.  
  2302. 12.13 Accessing fields
  2303.  
  2304. CSDBGEN generates two member functions for each field. One to read
  2305. the field, and a second to write the field. The names are the same but
  2306. the arguments differ.
  2307.  
  2308.  
  2309.  
  2310. Example:
  2311.  
  2312. // A part of the definition file:
  2313.       class: NAM
  2314.       record: nam_record
  2315.       file: dbtest
  2316.       field: name s 40
  2317.       field: number i
  2318.  
  2319. // We have a 'name' field consisting of a string with 40 characters
  2320. // and a 'number' field which is an integer.
  2321. // Among others, the next member functions are generated by CSDBGEN:
  2322.  
  2323. class NAM
  2324. {
  2325. public:
  2326. // For reading
  2327.       char  *name(void);
  2328.       int    number(void);
  2329. // For writing
  2330.       void   name(char *s);
  2331.       void   number(int i);
  2332. };
  2333.  
  2334.  
  2335. The next example gives an impression of how the generated class
  2336. could be used.
  2337.  
  2338.  
  2339. Example:
  2340.  
  2341.    void main(void)
  2342.    {
  2343.       NAM db;            // We now have a class 'NAM'.
  2344.  
  2345.       db.open();        // Open database. Assuming it already exists.
  2346.                 // No file names have to be entered.
  2347.                 // All the indexes are opened automatically.
  2348.  
  2349.       puts(db.name());        // Displays the name field of the first record.
  2350.                 // After 'open' the first record is 'current'.
  2351.  
  2352.       db.name("Pjotr Idaho"); // Changes the contents of the 'name' field to
  2353.              // 'Pjotr Idaho'. Indexes are updated automatically.
  2354.  
  2355.       db.close();        // Close database.
  2356.    }
  2357.  
  2358.  
  2359.  
  2360.  
  2361. 12.14 DATE fields
  2362.  
  2363. Standard C doesn't support date variables. Therefore, this library has
  2364. its own DATE class.
  2365.  
  2366. The functions to read and write date-fields are using a string
  2367. representation of a date. These strings can represent a date in several
  2368. formats. CSDBGEN uses a default of DMY4. This means 2 positions for
  2369. the Day, 2 positions for the Month and 4 positions for the Year.
  2370.  
  2371.  
  2372. Example:
  2373.  
  2374.    "02/04/1994"    // By default interpreted as:  April the 2th 1994.
  2375.  
  2376.  
  2377. When a two position representation of the year is wanted, use Y2
  2378. instead of Y4.
  2379. Every order of M,D,Y2 or Y4 is acceptable.
  2380.  
  2381.  
  2382. Example:
  2383.     If you want "02/04/94"  to be interpreted as February the 4th 1994, use the format
  2384.     MDY2. The line in the database definition file has to be:
  2385.  
  2386.     field: birthday d MDY2
  2387.  
  2388.     If you want the field to be indexed, add an additional 'Y':
  2389.  
  2390.     field: birthday d MDY2 Y
  2391.  
  2392.  
  2393. For more information about the date formats, please see the
  2394. documentation of the DATE class in the CSA-library.
  2395.  
  2396. On disk, dates are stored as longs.
  2397.  
  2398.  
  2399. 12.15 Changing the record layout.
  2400.  
  2401. Even when the database is already in use, the need to make changes
  2402. in the record layout may occur. With the next procedure this can be
  2403. accomplished quite easily, without to the need to reenter any record
  2404. manually.
  2405.  
  2406. To put it in a nut shell: save your data to an ASCII file with the old
  2407. export() function and reload with the new import() function.
  2408.  
  2409. Or in more detail:
  2410.  
  2411.     a) Export with the 'old' export() function.
  2412.     This will produce an ASCII file which fully resembles the
  2413.     database.
  2414.     b) Make a new definition file or alter the old one.
  2415.     c) Generate a new Class with CSDBGEN.
  2416.     d) Compile & link.
  2417.     The last three steps are simply the procedure for creating a
  2418.     database using CSDBGEN.
  2419.     e) Use the new import() function to reload the data.
  2420.     Import the ASCII file created with step 'a'. The import()
  2421.     function is doing the actual conversion. It can do this because
  2422.     it has knowledge of both the old and the new definition file.
  2423.     The old one is on top of the ASCII file and knowledge about
  2424.     the new one is hard coded in the import() function by
  2425.     CSDBGEN.
  2426.  
  2427.  
  2428. 12.16 Member functions in alphabetical order
  2429.  
  2430. Next is a list of the public member functions as they appear in the
  2431. generated class.
  2432. With the sole exception of open() and define(), the database needs to
  2433. be open for these functions to work properly.
  2434.  
  2435. void append_blank(void);
  2436.         Appends an additional record to the database. The
  2437.         record is filled with binary zeros and becomes the
  2438.         current record.
  2439. void bottom(void);
  2440.         The current record is set to the last record according
  2441.         to the active index.
  2442. void close(void);
  2443.         Closes the open files. All buffers are flushed and all
  2444.         allocated memory is released. This function is called
  2445.         automatically by the class destructor if needed.
  2446. long curr_rec(void);
  2447.         Returns the number of the current record. The first
  2448.         record is number 1.
  2449. void define(void);
  2450.         Creates a new database. Files are generated for the
  2451.         database and all the indexes.
  2452.         If a file already exists, it's overwritten.
  2453. void delet(void);
  2454.         Marks the current record for deletion. After the pack()
  2455.         function is called all the, in this way marked, records
  2456.         will be removed from the database.
  2457. int export(char *filename);
  2458.         Writes the contents of the database to an ASCII file
  2459.         'filename'. This file is meant to be read back by the
  2460.         import() function. The exported file contains a header
  2461.         which resembles the database 'definition file'. The
  2462.         function returns TRUE on succes, FALSE otherwise.
  2463. void go_to(long rec_nr);
  2464.         The record 'rec_nr' becomes the current record. This
  2465.         is independent of the active index! The record is
  2466.         directly looked up in the main database, not through
  2467.         an index. Whether or not the record is marked for
  2468.         deletion makes no difference.
  2469. int import(char *filename);
  2470.         Reads records from an ASCII file 'filename' generated
  2471.         by the export() function and appends these records to
  2472.         the database. TRUE is returned on success, FALSE
  2473.         otherwise.
  2474. int is_delet(void);
  2475.         This function returns TRUE if the current record is
  2476.         marked for deletion, FALSE otherwise.
  2477. long numrec(void);
  2478.         Returns the number of records currently in the
  2479.         database. The records marked for deletion are also
  2480.         counted.
  2481. void open(void);
  2482.         Opens the database for use. The define() function
  2483.         has to be called, that is, the database file needs to
  2484.         exist. Index files are automatically generated if they
  2485.         are missing. A runtime error is produced if something
  2486.         fails.
  2487. int order(void);    Returns the number of the current active index.
  2488. void order(int index_number);
  2489.         This function controls the use of indexes. The
  2490.         variable 'index_number' indicates which index has to
  2491.         become the active index. All the indexes however,
  2492.         are updated when a record is altered. In the header
  2493.         file a preprocessor constant is defined for each index.
  2494.         The name of this constant is generated by converting
  2495.         the field name to upper case and adding _INDEX.
  2496.  
  2497.     Example:
  2498.        An index on field:    Street
  2499.        Preprocessor constant:    STREET_INDEX
  2500.        <Class>.order(STREET_INDEX);
  2501.        will make the index on the street field the active index.
  2502.        <Class>.order(UNSORTED);
  2503.        makes all the indexes inactive.
  2504.  
  2505.         Changing the active index does not alter the current
  2506.         record. The preprocessor constant UNSORTED can
  2507.         be used to render all the indexes inactive. The
  2508.         database will be browsed in its 'natural' order.
  2509. void pack(void);
  2510.         Removes all the records marked for deletion. No
  2511.         temporary files are used!
  2512. void reindex(void);
  2513.         Rebuilds all the indexes of the database.
  2514. void search(void *key);
  2515.         The active index is searched for value 'key'. The
  2516.         current record becomes the first record which
  2517.         matches the search value. The function accepts a
  2518.         pointer to the search argument. The reason is that
  2519.         the indexes are not (necessarily) of the same type.
  2520.         E.g. one index may search for integers while another
  2521.         searches for strings. In this way the same search
  2522.         function can be used, no matter the field type. When
  2523.         the search argument is not exactly matched, the
  2524.         current record becomes the record with a value 'close
  2525.         to' the required key. Normally this will be the next
  2526.         'higher' value. This strategy proofs to work fine when
  2527.         searching for names etc..
  2528. int skip(int delta);
  2529.         Makes another record the current record.
  2530.  
  2531.     Examples:
  2532.        skip(1);     // The next record becomes the current record.
  2533.        skip(-1);    // The previous record becomes the current record.
  2534.        skip(0);     // Nothing happens.
  2535.        skip(10);    // The record 10 positions to the end becomes
  2536.             // the current record.
  2537.  
  2538.         If an attempt is made to go 'before' the first record,
  2539.         record number 1 becomes the current record. Similar,
  2540.         the last record becomes the current record if an
  2541.         attempt is made to pass beyond the last record. The
  2542.         order in which the records are traversed is controlled
  2543.         by the current active index. The function returns the
  2544.         number of positions actually moved.
  2545. int to_DBASE(char *filename);
  2546.         Exports the database to a file 'filename', which can
  2547.         be read by dBASE.
  2548.         Index files (for dBASE) are NOT generated.
  2549. void top(void);
  2550.         The current record is set to the first record according
  2551.         to the active index.
  2552. void undelet(void);
  2553.         If the current record is marked for deletion, this
  2554.         function removes the marker. Otherwise nothing
  2555.         happens.
  2556.  
  2557.  
  2558. 12.17 Warning
  2559.  
  2560. The program generator is not 'fool proof'. This means that you
  2561. should avoid using names which already are reserved C++
  2562. key words. E.g. if you try to define a field with the name
  2563. 'delete' the resulting source will not compile.
  2564.  
  2565. 12.18 Example
  2566.  
  2567. Let's say we want to build a database with stores a person's name and
  2568. his/hers birthday.
  2569.  
  2570. Step 1
  2571.  
  2572. First we need to construct a definition file. Next is a working example.
  2573.  
  2574.  
  2575. class:    BIRTH
  2576. record: BRecord
  2577. file:    bdays
  2578. field:    name      s 30 T
  2579. field:    birthday  d Y4MD Y
  2580.  
  2581.  
  2582. Assumes the name of this definition file is 'birth.def'.
  2583.  
  2584.  
  2585. Step 2
  2586.  
  2587. From the definition file we have to generate the source for the
  2588. database. We do that by calling CSDBGEN.
  2589.  
  2590.  
  2591. c:\borlandc\csutil\test> csdbgen birth.def
  2592.  
  2593.  
  2594.  
  2595. This produces two output files: 'birth.cpp' and 'birth.h'.
  2596. These names are derived from the name of the definition file. Not from
  2597. the class name as one might expect from this example.
  2598.  
  2599.  
  2600. Step 3
  2601.  
  2602. We are now ready to start compiling. Normally, creating the database
  2603. will be an option in the main menu of the application, but because this
  2604. is a demonstration we do things differently.
  2605.  
  2606.  
  2607. #include "birth.h"
  2608.  
  2609. void main(void)
  2610. {
  2611.  
  2612.    BIRTH db;    // Declare an instance of the new BIRTH class.
  2613.  
  2614.    db.define(); // Create the database and its indexes.
  2615.  
  2616. }
  2617.  
  2618.  
  2619. Compile this together with the 'birth.cpp' file and link it.
  2620.  
  2621. When ran, it should create three files:
  2622. - 'bdays.dbf'   The TBASE main database file.
  2623. - 'bdays01.idx' The BTREEa index on the field name.
  2624. - 'bdays02.idx' The BTREEl index on the field birthday. Remember,
  2625.         dates are stored as longs.
  2626.  
  2627. If you run CSDIR in the same directory it will show something like this:
  2628.  
  2629.  
  2630.  
  2631. Directory C:\BORLANDC\CSUTIL\TEST\
  2632.  
  2633. Name            Size      Type    Entries     Created     Updated
  2634. --------------------------------------------------------------------------
  2635. BDAYS.DBF         174      TBASE          0   Nov 01 1994  Nov 01 1994
  2636. BDAYS01.IDX         174      BTREEa          0   Nov 01 1994  Nov 01 1994
  2637. BDAYS02.IDX         174      BTREEl          0   Nov 01 1994  Nov 01 1994
  2638. --------------------------------------------------------------------------
  2639. Total:             522 bytes in   3 files.
  2640.  
  2641.  
  2642.  
  2643.  
  2644. Step 4
  2645.  
  2646. By now, we have created the database files and we have the class to
  2647. work with it. In other words, we are ready to write an 'application'.
  2648.  
  2649.  
  2650.  
  2651. #include "iostream.h"
  2652. #include "birth.h"
  2653.  
  2654. void main(void)
  2655. {
  2656.  
  2657.    BIRTH db;        // Declare an instance of the new BIRTH class.
  2658.  
  2659.    db.open();        // Open it. Because it's empty, a blank record
  2660.             // is automatically added and becomes the current.
  2661.  
  2662.    db.name("Luke Skywalker");   // Modify the name.
  2663.    db.birthday("2015/07/03");   // Modify the birthday.
  2664.  
  2665.    db.append_blank();        // Add a new record. Becomes the current.
  2666.  
  2667.    db.name("Al Bundy");         // Modify the name.
  2668.    db.birthday("1945/11/30");   // Modify the birthday.
  2669.  
  2670.    db.reindex();        // Reindexing. For demonstration purposes.
  2671.                 // Shouldn't be necessary.
  2672.  
  2673.    db.order(BIRTHDAY_INDEX);    // Make BIRTHDAY the active index.
  2674.    db.top();            // Go to the oldest person.
  2675.    do
  2676.    { cout<<db.name()<<endl; }    // Display his name.
  2677.    while(db.skip(1));        // Skip to the next.
  2678.  
  2679.    db.go_to(1);         // Make record 1 the current record.
  2680.                 // Index INdependent!
  2681.    db.delet();            // Mark it for deletion.
  2682.    db.pack();            // Remove it from the database.
  2683.  
  2684.    db.close();            // Close database and indexes.
  2685. }
  2686.  
  2687.  
  2688.  
  2689. If you run CSDIR again afterwards, you will see something like this:
  2690.  
  2691.  
  2692.  
  2693. Directory C:\BORLANDC\CSUTIL\TEST\
  2694.  
  2695. Name            Size      Type    Entries     Created     Updated
  2696. --------------------------------------------------------------------------
  2697. BDAYS.DBF        4096      TBASE          1   Nov 01 1994  Nov 01 1994
  2698. BDAYS01.IDX        3072      BTREEa          1   Nov 01 1994  Nov 01 1994
  2699. BDAYS02.IDX        3072      BTREEl          1   Nov 01 1994  Nov 01 1994
  2700. --------------------------------------------------------------------------
  2701. Total:           10240 bytes in   3 files.
  2702.  
  2703.  
  2704.  
  2705.  
  2706.  
  2707.  
  2708.  
  2709.  
  2710.  
  2711.  
  2712.  
  2713.  
  2714.  
  2715.  
  2716.                     Part
  2717.  
  2718.                    Three
  2719.  
  2720.  
  2721.  
  2722.  
  2723.  
  2724.  
  2725.  
  2726.  
  2727.  
  2728.  
  2729.  
  2730.  
  2731.  
  2732.  
  2733.  
  2734.  
  2735.  
  2736.  
  2737.  
  2738.  
  2739.  
  2740.  
  2741.       Next are some classes which can be used where the traditional
  2742.               database will not do.
  2743.       A VRAM class is discussed which makes it possible to maintain
  2744.                pointer structures on disk.
  2745.        Two other classes, VBASE and VBAXE, are presented which deal
  2746.               with variable length records.
  2747.     In particular the beautiful VRAM class deserves attention!
  2748.  
  2749.  
  2750.                    13 VRAM
  2751.  
  2752. 13.1 Introduction
  2753.  
  2754. VRAM is without any doubt the most flexible and versatile class in this
  2755. library. Contrary to the traditional database, this one doesn't suffer from
  2756. fixed record sizes and doesn't have problems with deletions.
  2757. In other words: it isn't a database at all!
  2758.  
  2759. Assuming a C++ programmer has a good understanding of a 'heap', it
  2760. shouldn't take long to explain this class. In one sentence, VRAM
  2761. mimics a 'heap on a disk'.
  2762.  
  2763. The idea is simple: use functions like 'malloc' and 'free' to manipulate
  2764. the necessary space, just like with an ordinary heap, only this time the
  2765. heap is in fact a file. In this way the data is not lost when the program
  2766. exits while all the flexibility of a heap is still there!
  2767.  
  2768. In a nut shell, that's what this class does. Apart from the indispensable
  2769. functions 'define', 'open' and 'close', the class has mainly two functions:
  2770. 'malloc()' and 'free()'.
  2771.  
  2772.  
  2773. 13.2 Creating
  2774.  
  2775.     int define(char *name,U16 struclen);
  2776.  
  2777. This is the function needed to create a VRAM system.
  2778. Contrary to what you might have expected, it takes two parameters.
  2779. The first is as usual the file name, the second however, is the
  2780. maximum size you are planning to allocate.
  2781.  
  2782. This differs from the ordinary heap which simply accepts allocations of
  2783. any size right from the start. (Which also explains why the ordinary
  2784. heap allocations are so amazingly inefficient.)
  2785.  
  2786. In a way, the second parameter 'struclen' is a performance parameter.
  2787. If you like, you could always use the maximum, which is 32 Kb, but this
  2788. would yield a highly inefficient VRAM. The VRAM system will perform
  2789. better the more accurate 'struclen' reflects the true state of affairs.
  2790. However, performance option or not, 'struclen' is a very absolute upper
  2791. limit to what you are allowed to allocate. Any attempt to allocate more
  2792. will be answered with a runtime error.
  2793.  
  2794.  
  2795. // Example VRAM define()
  2796.  
  2797. #include "CSVRAM.H"
  2798.  
  2799. void main(void)
  2800. {
  2801.  
  2802.     VRAM vr;
  2803.     vr.define("VRAM.TST",614);  // Allocating at most 614 bytes.
  2804.  
  2805. }
  2806.  
  2807.  
  2808.  
  2809. The CSDIR utility recognizes VRAM files. Afterwards it will display
  2810. something like:
  2811.  
  2812.  
  2813. Directory C:\BORLANDC\TEST\VRAM\
  2814.  
  2815. Name            Size      Type    Entries     Created     Updated
  2816. --------------------------------------------------------------------------
  2817. VRAM.TST         174      VRAM          0   Nov 18 1994  Nov 18 1994
  2818. --------------------------------------------------------------------------
  2819. Total:             174 bytes in   1 files.
  2820.  
  2821.  
  2822.  
  2823. 13.3 Opening & Closing
  2824.  
  2825. Like all the databases classes in this library, VRAM needs to be
  2826. 'opened' before it can be used and, consequently, 'closed' afterwards.
  2827.  
  2828. syntax: int open(char *name,U16 kb_buf);
  2829.  
  2830. This opens the vram file 'name' and uses 'kb_buf' Kb for buffering.
  2831.  
  2832. syntax: int close(void);
  2833.  
  2834. This closes the VRAM system. This function is also called by the class
  2835. destructor when needed.
  2836.  
  2837.  
  2838. // Example VRAM
  2839.  
  2840. #include "CSVRAM.H"
  2841.  
  2842. void main(void)
  2843. {
  2844.  
  2845.     VRAM vr;
  2846.     vr.define("VRAM.TST",614);  // Allocating at most 614 bytes.
  2847.  
  2848.     vr.open("VRAM.TST",300);    // Opens VRAM.TST using 300 Kb buffers.
  2849.  
  2850.     // Doing something interesting.
  2851.  
  2852.     vr.close();         // Close VRAM system.
  2853. }
  2854.  
  2855.  
  2856.  
  2857.  
  2858. 13.4 VRAM Pointers
  2859.  
  2860. The normal malloc() function returns a void pointer, unfortunate VRAM
  2861. cannot do that. It uses its own type of pointer: VPOI which is short for
  2862. Virtual POInter. VPOI is a simple 32 bit unsigned long, defined in
  2863. 'CSVRAM.H'. VPOI also limits the size of a VRAM system. With 32 bits
  2864. 4 Gb can be addressed, no more. Of course you can always use more
  2865. then one VRAM system in your application when pressed for space!
  2866.  
  2867. There is another important difference between VRAM and a normal
  2868. heap. VRAM distinguishes between reading and writing. The buffer
  2869. system used, cannot tell whether you are making changes. Therefore,
  2870. the programmer need to supply that information by calling different
  2871. functions for reading and writing.
  2872.  
  2873. Reading:    char *R(VPOI p);
  2874. Writing:    char *W(VPOI p);
  2875.  
  2876.  
  2877. // Example
  2878.  
  2879. #include "CSVRAM.H"
  2880.  
  2881. void main(void)
  2882. {
  2883.  
  2884.     VRAM vr;            // A VRAM system.
  2885.     VPOI vp;            // A VRAM pointer.
  2886.     char *cp;            // A normal character pointer.
  2887.  
  2888.     vr.define("VRAM.TST",614);  // Initially create it.
  2889.  
  2890.     vr.open("VRAM.TST",50); // Opening with 50 kB buffers.
  2891.  
  2892.     vp=vr.malloc(20);        // Allocate 20 bytes from the virtual heap.
  2893.  
  2894.     cp=vr.W(vp);        // Obtaining a character pointer to
  2895.                 // the allocated space. We are planning to
  2896.                 // write, so the 'W' function is used.
  2897.  
  2898.     strcpy(cp,"Some Data"); // Write data into it.
  2899.  
  2900.     vr.close();         // Close the VRAM system.
  2901.                 // "Some Data" is now on disk!
  2902.  
  2903. }
  2904.  
  2905.  
  2906.  
  2907. From the above example it becomes clear how the VPOI pointers can
  2908. be used. The method is simple: convert them into normal pointers and
  2909. apply standard C++ programming technique.
  2910.  
  2911. Only the last 2 converted VPOI pointers are guaranteed to be
  2912. valid. VRAM has a limited number of buffers, so you cannot
  2913. expect all data to be in ram forever.
  2914. Every time you convert a VPOI pointer into a character pointer by using
  2915. the W() or the R() function, VRAM calculates the corresponding position
  2916. in the file and loads the required page in ram. The pointer returned
  2917. points directly into this page. Because only the last two pages are
  2918. guaranteed to be in ram under all circumstances, the third time you
  2919. convert a VPOI pointer, it can overwrite a previously loaded page.
  2920.  
  2921. Because at least two pointers are valid, you can copy data from one
  2922. VRAM position to another without using temporary storage.
  2923.  
  2924. With the W() function, the loaded page is marked 'dirty' which makes
  2925. sure it's written back to disk when the page is removed from the buffer
  2926. system. This is not so for the R() function. In that case the page is
  2927. simply discarded.
  2928.  
  2929.  
  2930. // Example, copying between two VPOI pointers.
  2931.  
  2932. #include "CSVRAM.H"
  2933. void main(void)
  2934. {
  2935.  
  2936.     VRAM vr;
  2937.     VPOI vp1,vp2;
  2938.  
  2939.     vr.open("VRAM.TST",50);           // Opening with 50 kB buffers.
  2940.  
  2941.     strcpy(vr.W(vp1=vr.malloc(20)),"Some Data");    // Allocate and fill
  2942.                       // one VPOI.
  2943.  
  2944.     vp2=vr.malloc(100);           // Allocate a second.
  2945.  
  2946.     memcpy(vr.W(vp2),vr.R(vp1),20);   // Copy!
  2947.  
  2948.     vr.close();               // Close the VRAM system.
  2949. }
  2950.  
  2951.  
  2952.  
  2953. 13.5 Fragmentation
  2954.  
  2955. Just as with an ordinary heap, VRAM can suffer from fragmentation.
  2956. The normal heap can become prematurely exhausted because of
  2957. fragmentation while for the VRAM system it only means the file
  2958. becomes larger then strictly necessary.
  2959. On the other hand: the normal heap gets a fresh start every time the
  2960. program is run while the VRAM files may be in use for years.
  2961.  
  2962. Therefore a defrag() function is available. If you decide to use it, it is
  2963. best to use it regularly. It mainly does three things:
  2964. a)  Joining free space wherever possible.
  2965.     This is not done during normal operation because it may involve
  2966.     additional IO.
  2967. b)  Sorting the empty-data-chains.
  2968.     When space is needed, its taken from the beginning of a empty-
  2969.     chain. After sorting the chains, the empty blocks at the beginning
  2970.     of the file will also be at the beginning of the chain. Eventually this
  2971.     leads to pages at the end becoming completely free and pages at
  2972.     the beginning (almost) full.
  2973. c)  Empty pages above the highest used location are stripped from the
  2974.     file.
  2975.  
  2976. The defrag() function links in a lot of code, it uses an entire
  2977. btree and a temporary file. In a way this makes the defrag()
  2978. function 'bigger' then the rest of the VRAM class combined!
  2979.  
  2980. 13.6 Root
  2981.  
  2982. Under some circumstances you may need a 'starting point' in the
  2983. VRAM.
  2984. Example:
  2985.     Let's say you are writing some flowcharting program and you have
  2986.     decided that VRAM is a great help in storing and manipulating a
  2987.     flowchart. The flowchart probably consists of several independent
  2988.     parts pointered together. Once in it, each part can be reached by
  2989.     the VPOI's stored in the data structure. This leaves you with just
  2990.     one problem: where does the flowchart start?
  2991.     It takes just one VPOI to store that location and it would be a
  2992.     shame if you needed an additional configuration file for that.
  2993.  
  2994. Therefore two very simple functions are implemented to store and
  2995. retrieve a 'special' VPOI.
  2996.  
  2997. void  root(VPOI p);    Stores VPOI 'p'.
  2998. VPOI root(void);    Obtains the VPOI stored with the previous
  2999.             function.
  3000.  
  3001. These functions just manipulate this single VPOI. They have absolutely
  3002. no effect on the rest of the VRAM system.
  3003.  
  3004. 13.7 Functions in Alphabetical order.
  3005.  
  3006. Prototypes are in 'csvram.h'. With the exception of the define(). open()
  3007. and zap() functions, the class needs to be opened for the functions to
  3008. work.
  3009.  
  3010. U16 alloc(VPOI p);
  3011. U16 alloc(void *p);
  3012.         Returns the number of allocated bytes at a certain
  3013.         location. The pointer may be either a VPOI pointer or
  3014.         a normal pointer to the same location.
  3015. int close(void);    Closes the VRAM system. Returns TRUE on
  3016.             success, FALSE otherwise.
  3017. int define(char *name,U16 struclen);
  3018.         Creates the VRAM system 'name' with 'struclen'
  3019.         being the maximum size of any allocation. Returns
  3020.         TRUE on success, FALSE otherwise.
  3021. int defrag(void);   Defragments the virtual heap. Returns TRUE on
  3022.             success, FALSE otherwise.
  3023. int empty(void);    Makes the VRAM system empty. The class remains
  3024.             open but all allocations will be undone. Returns
  3025.             TRUE on success, FALSE otherwise.
  3026. U32 number(void);
  3027.         Returns the number of allocations currently done.
  3028.         This is the number of malloc()'s minus the number of
  3029.         free()'s.
  3030. int open(char *name,S16 kb_buf);
  3031.         Opens VRAM 'name' using 'kb_buf' Kb ram for
  3032.         buffering. Returns TRUE on success, FALSE
  3033.         otherwise.
  3034. char *R(VPOI p);
  3035.         Converts a VPOI pointer into a character pointer. It is
  3036.         assumed no modifications are going to take place.
  3037. void  root(VPOI p);
  3038.         Stores VPOI 'p'.
  3039. VPOI root(void);    Obtains the VPOI stored with the previous functions.
  3040. int save(void); Makes a safety backup. The VRAM system remains
  3041.         open. All the buffers are flushed and the header page
  3042.         is updated. Returns TRUE on success, FALSE
  3043.         otherwise.
  3044. void free(VPOI p);
  3045.         Frees the VPOI p.
  3046. VPOI malloc(U16  size);
  3047.         Allocates 'size' amount of bytes from the virtual heap.
  3048.         The corresponding VPOI is returned.
  3049. char *W(VPOI p);
  3050.         Converts a VPOI pointer into a character pointer. It is
  3051.         assumed modifications are going to take place.
  3052. int zap(void);    Closes the VRAM system when needed and restores
  3053.         all class defaults. Returns TRUE on success, FALSE
  3054.         otherwise.
  3055.  
  3056.                    14 VBASE
  3057.  
  3058.  
  3059. 14.1 Introduction
  3060.  
  3061. The use and purpose of the VBASE class are much similar to the
  3062. TBASE class. There is however, one huge difference, VBASE supports
  3063. variable length records! The 'V' in VBASE stands for 'variable'.
  3064.  
  3065. Compared with TBASE, the differences in the public member functions
  3066. are minimal. The append() function now takes an additional parameter
  3067. indicating the length of the record. The same goes for the write_rec()
  3068. function. Apart from the 'normal' read_rec() function there is now an
  3069. additional read_rec() which returns the length of the obtained record.
  3070.  
  3071. VBASE is a 'stand alone' class. It has nothing to do with the
  3072. databases produced by CSDBGEN.
  3073.  
  3074.  
  3075.  
  3076. 14.2 Using VBASE.
  3077.  
  3078. Using VBASE is very straightforward.
  3079.  
  3080. - Initially create the VBASE system by calling define().
  3081. - Open it through a call to open().
  3082. - Read, write and append records.
  3083. - Close VBASE by calling close().
  3084.  
  3085. That's all!
  3086.  
  3087.  
  3088. // Example
  3089.  
  3090. #include "csvbase.h"
  3091.  
  3092. void main(void)
  3093. {
  3094.  
  3095.     VBASE vb;
  3096.  
  3097.     vb.relocate_when_shrunk(TRUE);  // Move the record to a better
  3098.                     // fitting position when shrunk.
  3099.     vb.define("VBASE.dbf",1230);    // Maximum record length 1230 bytes.
  3100.  
  3101.     vb.open("VBASE.dbf", 200);      // Open with 200 Kb buffers.
  3102.  
  3103.     char *s="Some chunk of data. ";
  3104.  
  3105.     vb.append_rec(s,strlen(s)+1);   // Append a record. Notice the length
  3106.                     // parameter which is not needed with
  3107.                     // TBASE.
  3108.     char d[200];
  3109.     vb.read_rec(1,d);            // Read record 1 into array 'd'.
  3110.  
  3111.     strcpy(d,"New Data");
  3112.  
  3113.     vb.write_rec(1,d,strlen(d)+1);  // Overwrite record 1 with a new
  3114.                     // block of data. This does not have
  3115.                     // to have the same length!
  3116.  
  3117.     vb.close();             // Ready. Close VBASE. Also called by
  3118.                     // the class destructor if needed.
  3119.  
  3120. }
  3121.  
  3122.  
  3123. For more information, please read the documentation on the TBASE
  3124. class.
  3125.  
  3126.  
  3127. 14.3 Relocating records
  3128.  
  3129. When an existing record is overwritten with a new bigger record, it no
  3130. longer fits in its original slot, which means the record has to be
  3131. relocated. This is not necessarily so when the record shrinks. In that
  3132. case you have the choice between relocating, which saves disk space
  3133. but is relatively slow or leaving the record where it is and waste some
  3134. disk space.
  3135.  
  3136. The function 'relocate_when_shrunk()' is there to choose between these
  3137. two strategies. It has to be called before 'define()'.
  3138. Calling 'relocate_when_shrunk(TRUE);' will relocate a record when it
  3139. becomes smaller. 'Relocate_when_shrunk(FALSE);' will leave the
  3140. records in place when possible.
  3141. The default is set to: relocate_when_shrunk(TRUE).
  3142.  
  3143. The function has to be called before 'define()' and its setting
  3144. cannot be altered afterwards.
  3145.  
  3146.  
  3147.  
  3148. 14.4 Limitations.
  3149.  
  3150. VBASE was designed for databases up to around a million records.
  3151. This is not a 'hard' limit, its possible to add many more records but
  3152. under some unfavourable conditions memory utilization can get out of
  3153. control. The way the class uses the available ram is controlled by the
  3154. open() function. The worst thing you can do is open an empty VBASE
  3155. and append 3 million records in one go. In this way the class cannot
  3156. adjust the way its using memory. If the records are not appended all at
  3157. once but with several close/open sequences in between, VBASE can
  3158. easily store 16 million records.
  3159.  
  3160. So:
  3161. - Under worst case conditions 1 million records.
  3162. - Under favourable conditions 16 million records.
  3163. - Avoid more then 16 million records.
  3164.  
  3165. The above limitations stem from ram utilization. For those drowning in
  3166. memory, there are also software limitations:
  3167. - maximum file size 4 Gb.
  3168. - 4 billion records.
  3169.  
  3170.  
  3171. Because there are so many 'buts' and 'ifs', there is another class
  3172. VBAXE, discussed in the next chapter, to deal with the larger
  3173. databases.
  3174.  
  3175. As a rule of thumb, use VBASE for databases up to 1 million
  3176. records and VBAXE for more then 1 million records.
  3177.  
  3178. 14.5 Functions in alphabetical order.
  3179.  
  3180. The function prototypes are in csvbase.h.
  3181.  
  3182.  
  3183. U32 append_rec(void *data,U16 len);
  3184.         Append a record to the database. 'data' is a pointer
  3185.         to the data and 'len' is the number of bytes data. The
  3186.         function returns the number of the newly created
  3187.         record.
  3188. int close(void);
  3189.         Closes the database. All buffers are flushed and all
  3190.         allocated memory is freed. TRUE is returned on
  3191.         success, FALSE otherwise.
  3192. int define(char *name,U16 struclen);
  3193.         Creates a new database. 'name' is the name of the
  3194.         file and 'struclen' is the maximum length of a record.
  3195.         Do not make 'struclen' unnecessary large because its
  3196.         value is important for space efficiency. The maximum
  3197.         value of struclen is 32767. TRUE is returned on
  3198.         success, FALSE otherwise.
  3199. void delet(U32 record);
  3200.         Marks record 'record' for deletion. Only the 'delete bit'
  3201.         is set. The pack() function needs to be called to
  3202.         actually remove the record from the file.
  3203. void empty(void);
  3204.         Removes all records from the database. Upon return
  3205.         the database will contain zero records but will still be
  3206.         'open'.
  3207. int is_delet(U32 record);
  3208.         Returns TRUE if record 'record' is marked for
  3209.         deletion. FALSE otherwise.
  3210. U32 numvrec(void);
  3211.         Returns the number of records currently in the
  3212.         database.
  3213. int open(char *name,U16 kb_buf);
  3214.         Opens database 'name', using 'kb_buf' Kb ram for
  3215.         buffering. Returns TRUE on success, FALSE
  3216.         otherwise.
  3217. int pack(void); Removes all records marked for deletion. A
  3218.         temporary file is used. TRUE is returned on success,
  3219.         FALSE otherwise.
  3220. void read_rec(U32 rec,void *ptr,U16  &length);
  3221.         Reads record 'rec' and copies it into the buffer 'ptr' is
  3222.         pointing at. The variable 'length' is set to the length of
  3223.         the retrieved record.
  3224. void read_rec(U32 pos,U16  maxlen,void *ptr,U16  &length);
  3225.         The same as the precious function but with an
  3226.         additional parameter 'maxlen' specifying the
  3227.         maximum number of bytes that can be copied into
  3228.         the buffer 'ptr'. If the record proofs to be longer then
  3229.         'maxlen', only 'maxlen' bytes will be copied to 'ptr'.
  3230. U16 rec_len(U32 rec);
  3231.         Returns the length of record 'rec'.
  3232. void relocate_when_shrunk(int TrueOrFalse);
  3233.         When called with 'TrueOrFalse' set to TRUE, records
  3234.         will be relocated when shrunk. When called with
  3235.         FALSE the records will stay at the same place. The
  3236.         function has to be called before define(). For more
  3237.         information, please see the paragraph about this
  3238.         topic.
  3239. int save(void); As a precaution measure, all 'dirty' buffers are written
  3240.         to disk and the header page is updated. The
  3241.         database remains open. Returns TRUE on success
  3242.         and FALSE otherwise.
  3243. void undelet(U32 rec);
  3244.         Removes the 'delete' marking from record 'rec'.
  3245. void write_rec(U32 rec,void *data,U16 len);
  3246.         Overwrites the existing record 'rec'. 'len' bytes are
  3247.         copied from 'data'. Afterwards the record will be of
  3248.         length 'len'.
  3249.  
  3250.                    15 VBAXE
  3251.  
  3252. 15.1 Introduction
  3253.  
  3254. As explained in the previous chapter, VBAXE is similar to VBASE but is
  3255. intended for larger databases. That is, more then 1 million records.
  3256.  
  3257. The public member functions of the classes are 100% identical. The
  3258. inner workings however are completely different. VBAXE uses two files
  3259. for a database where as VBASE uses only one. VBAXE is build from
  3260. two other classes namely TBASE and VRAM.
  3261.  
  3262. Building a class for variable length records is not easy, but writing one
  3263. that can store millions of records, is fast, uses little ram, doesn't use
  3264. unnecessary disk space and still stores everything in one file is next to
  3265. impossible.
  3266. So, rather then coming up with something slow & clumsy, VBAXE gives
  3267. up on storing everything in one file which seems to be the lesser evil.
  3268.  
  3269.  
  3270. 15.2 Working.
  3271.  
  3272. The working of VBAXE is very simple. It allocates the necessary space
  3273. from VRAM and stores the VRAM pointer together with the length in a
  3274. TBASE record.
  3275. E.g. to obtain record 714 it starts with retrieving record 714 from
  3276. TBASE. Because TBASE uses fixed size records, the position of record
  3277. 714 can easily be calculated. Once this record is obtained, the VRAM
  3278. pointer to the data of record 714 is known. From this pointer the
  3279. position in the VRAM file can again be easily calculated. If nothing is in
  3280. the buffers, it takes two IO's to obtain the data, but at least no
  3281. searching is done. The positions in the files are always known through
  3282. simple arithmetic. (This also holds for the VBASE class.)
  3283.  
  3284.  
  3285. 15.3 Files
  3286.  
  3287. As explained above there are two files to every VBAXE database. The
  3288. TBASE part stores it's data in a file with extension '.vbi'. The VRAM
  3289. part uses extension '.vbd'. No matter what names are used in the
  3290. define() or the open() functions, these are the extensions used.
  3291. The CSDIR utility recognizes these files and will display the TBASE
  3292. class as VBASEi and VRAM as VBASEd. In this way its immediately
  3293. apparent they belong to the same database.
  3294.  
  3295.  
  3296. // Example
  3297.  
  3298. #include "csvbaxe.h"
  3299.  
  3300. void main(void)
  3301. {
  3302.     char buf[1000];
  3303.  
  3304.     VBAXE vb;
  3305.     vb.define("demo",390);      // Max record length 390 bytes.
  3306.  
  3307.     vb.open("demo",200);        // 200 Kb buffers.
  3308.  
  3309.     for(int i=1;i<=100;i++)
  3310.     {
  3311.     vb.append_rec(buf,1+random(390));   // Append 100 records
  3312.                         // with random length
  3313.                         // and random contents.
  3314.     }
  3315.  
  3316.     vb.close();         // Close database.
  3317. }
  3318.  
  3319.  
  3320. Afterwards CSDIR will display something like:
  3321.  
  3322.  
  3323.  
  3324. Directory C:\BORLANDC\DEMO
  3325.  
  3326. Name             Size      Type     Entries     Created  Updated
  3327. --------------------------------------------------------------------------
  3328. DEMO.VBI        4096      VBASEi        100   Dec 14 1994  Dec 14 1994
  3329. DEMO.VBD       26624      VBASEd        100   Dec 14 1994  Dec 14 1994
  3330. --------------------------------------------------------------------------
  3331. Total:           30720 bytes in    2 files.
  3332.  
  3333.  
  3334.  
  3335. However, CSINFO still says DEMO.vbi is a TBASE file and DEMO.vbd
  3336. a VRAM file.
  3337.  
  3338.  
  3339. 15.4 Prototypes.
  3340.  
  3341. The class defintion and it's function prototypes are in "CSVBAXE.H".
  3342.  
  3343.  
  3344.  
  3345.  
  3346.  
  3347.  
  3348.  
  3349.  
  3350.                     Part
  3351.  
  3352.                     Four
  3353.  
  3354.  
  3355.  
  3356.  
  3357.  
  3358.  
  3359.  
  3360.  
  3361.  
  3362.  
  3363.  
  3364.  
  3365.  
  3366.  
  3367.  
  3368.  
  3369.  
  3370.  
  3371.  
  3372.  
  3373.  
  3374.  
  3375.  
  3376.        Part Four will present some command-line utilities.
  3377.      Most noticeable CSDIR, which gives a quick survey of the
  3378.            databases in the current directory.
  3379.       It also discusses the demonstration application CSADD.
  3380.           CSADD is a DOS application to store addresses.                        16 CSDIR
  3381.  
  3382.  
  3383. CSDIR is an on-line utility similar to the well-known MS-DOS dir.
  3384. It's purpose is to list the CS-databases. By default it ignores all other
  3385. files.
  3386.  
  3387.     SYNTAX: csdir [filename] [/A] [/?]
  3388.  
  3389.     filename: the file(s) to be listed. Wildcards allowed.
  3390.     /A  List all files.
  3391.     /?  Display help.
  3392.  
  3393. Example of its output:
  3394.  
  3395.  
  3396. c:\bin\adres>csdir
  3397.  
  3398.  
  3399. Directory C:\BIN\ADRES\
  3400.  
  3401. Name            Size      Type    Entries     Created     Updated
  3402. --------------------------------------------------------------------------
  3403. CSADR.DBF       98382      TBASE        298   Sep 20 1994  Oct 31 1994
  3404. CSADR01.IDX       40960      BTREEa        403   Oct 29 1994  Oct 31 1994
  3405. CSADR02.IDX       10752      BTREEa        104   Oct 29 1994  Oct 31 1994
  3406. CSADR03.IDX        4608      BTREEl         28   Oct 29 1994  Oct 31 1994
  3407. CSADR04.IDX        5120      BTREEa         22   Oct 29 1994  Oct 31 1994
  3408. --------------------------------------------------------------------------
  3409. Total:          159822 bytes in   5 files.
  3410.  
  3411.  
  3412.  
  3413. As can be seen from this example, CSDIR displays:
  3414.     - the name of the class involved.
  3415.     - the number of entries in the database.
  3416.     - in case of a btree, the number of different keys. If the same key
  3417.     is entered twice, it is counted as one entry.
  3418.     - date of creation.
  3419.     - date of last update.
  3420.  
  3421. Example of the /a option.
  3422.  
  3423.  
  3424. c:\bin\adres>csdir /a
  3425.  
  3426.  
  3427. Directory C:\BIN\ADRES\
  3428.  
  3429. Name            Size      Type    Entries     Created     Updated
  3430. --------------------------------------------------------------------------
  3431. ADRES.EXE      137872       DOS                   Oct 29 1994
  3432. CSDEMIO.DEF         277       DOS                   Apr 17 1994
  3433. BACKUP.TXT       34478       DOS                   Oct 29 1994
  3434. CSADR.DBF       98382      TBASE        298   Sep 20 1994  Oct 31 1994
  3435. CSADR01.IDX       40960      BTREEa        403   Oct 29 1994  Oct 31 1994
  3436. CSADR02.IDX       10752      BTREEa        104   Oct 29 1994  Oct 31 1994
  3437. CSADR03.IDX        4608      BTREEl         28   Oct 29 1994  Oct 31 1994
  3438. CSADR04.IDX        5120      BTREEa         22   Oct 29 1994  Oct 31 1994
  3439. ERROR.ERR       12964       DOS                   Oct 27 1994
  3440. --------------------------------------------------------------------------
  3441. Database files:   159822 bytes in   5 files.
  3442. Other files:      185591 bytes in   4 files.
  3443.         -------- +      --- +
  3444. Total:          345413 bytes in   9 files.
  3445.  
  3446.  
  3447.  
  3448.  
  3449. Another example:
  3450.  
  3451.  
  3452. c:\bin\adres>csdir cs*.* /a
  3453.  
  3454.  
  3455. Directory C:\BIN\ADRES\
  3456.  
  3457. Name            Size      Type    Entries     Created     Updated
  3458. --------------------------------------------------------------------------
  3459. CSDEMIO.DEF         277       DOS                   Apr 17 1994
  3460. CSADR.DBF       98382      TBASE        298   Sep 20 1994  Oct 31 1994
  3461. CSADR01.IDX       40960      BTREEa        403   Oct 29 1994  Oct 31 1994
  3462. CSADR02.IDX       10752      BTREEa        104   Oct 29 1994  Oct 31 1994
  3463. CSADR03.IDX        4608      BTREEl         28   Oct 29 1994  Oct 31 1994
  3464. CSADR04.IDX        5120      BTREEa         22   Oct 29 1994  Oct 31 1994
  3465. --------------------------------------------------------------------------
  3466. Database files:   159822 bytes in   5 files.
  3467. Other files:         277 bytes in   1 files.
  3468.         -------- +      --- +
  3469. Total:          160099 bytes in   6 files.
  3470.  
  3471.  
  3472.  
  3473.  
  3474.  
  3475.                   17 CSINFO
  3476.  
  3477.  
  3478. CSINFO is an on-line DOS utility to display information about a
  3479. particular database.
  3480. It only recognizes the databases made with the CSDB-library.
  3481.  
  3482. An example of its output:
  3483.  
  3484.  
  3485.  
  3486. c:\adres>csinfo csadr01.idx
  3487.  
  3488.  
  3489.   Information about database: csadr01.idx.
  3490.  
  3491.    Type..................:  BTREEa
  3492.    Version...............:  1.0.a
  3493.    Class compiled at.....:  Sep 05 1994, 04:28:24
  3494.    With..................:  Borland C++ 3.1
  3495.  
  3496.  NOTE: The above information refers to the version of the
  3497.        class used during the CREATION of the database file.
  3498.  
  3499.    Btree created at......:  September 20 1994, 10:02:11,47
  3500.    Btree last updated at.:  September 26 1994, 23:25:19,96
  3501.    Multiple keys allowed.:  YES
  3502.    Number of keys........:  622
  3503.    Number of blocks......:  111
  3504.    Block size............:  511 bytes
  3505.    Key size..............:  41 bytes
  3506.    Data size.............:  4 bytes
  3507.    Data degree...........:  10
  3508.    Index degree..........:  10
  3509.    Number of levels......:  4
  3510.  
  3511.  
  3512.  
  3513.                   18 CSERROR
  3514.  
  3515.  
  3516. Normally all the errors are read from a file. This is the file 'error.err'.
  3517. It has to be in the current working directory or it cannot be found.
  3518.  
  3519. The advantage in using a runtime error file is of course the smaller
  3520. executable that results from leaving out all the possible error
  3521. messages.
  3522. The error file is not kept open all the time. For opening a file, some
  3523. dynamic memory allocations have to be done. This can lead to
  3524. problems when the error message that has to be displayed results from
  3525. an 'out of memory' condition.
  3526. (It needs memory to say 'there is no more memory'.)
  3527.  
  3528. To overcome this and other problems, CSERROR can be used.
  3529. It generates C source that makes the runtime error file redundant.
  3530.  
  3531.  
  3532. Example:
  3533. c:\borlandc>cserror error.err
  3534.  
  3535.  
  3536. This will produce a file 'error.cpp' in the current directory. Compile this
  3537. and link it in with the rest of your application, but before the libraries. In
  3538. this way the 'error.obj' will replace the 'csmess_read()' function which is
  3539. in the library.
  3540.  
  3541.  
  3542. // Example of how the resulting 'error.cpp' file could look:
  3543. // Many errors are left out.
  3544.  
  3545.  
  3546. #include "csmess.h"
  3547.  
  3548. char *_csa_error[]=
  3549.      {
  3550.        "Error 9370: TBASE: %s Can't write report file %s. Disk full?",
  3551.        "Error 9390: TBASE: %s Out of memory during pack().",
  3552.        "Fatal Error 9545: PAGE: %s Header_2_data(): can't perform fseek.",
  3553.        "Fatal Error 9550: PAGE: %s Write_header: can't perform fwrite.",
  3554.        "Fatal Error 9555: PAGE: %s Header_2_data(): can't perform fread.",
  3555.        "Fatal Error 9560: PAGE: %s Can't open file during definition.",
  3556.        "Error 9562: PAGE: %s Can't open report file %s.",
  3557.        "TheEnd"  //THIS HAS TO BE THE LAST LINE!!
  3558.      };
  3559.  
  3560. /////////////////////////////////////////////////////////////////////
  3561.  
  3562. char *csmess_read(long error)
  3563. {
  3564.    char tmp[25];
  3565.    ltoa(error,tmp,10);
  3566.    char **p=_csa_error;
  3567.    for(;;)
  3568.    {
  3569.       if(strstr(*p,tmp)) return *p;
  3570.       if(!strcmp(*p,"TheEnd")) return NULL;
  3571.       p++;
  3572.    }
  3573.  
  3574.  
  3575.  
  3576. Notice the 'TheEnd' line, which was not in the original
  3577. 'error.err' file. Never remove that line!
  3578.  
  3579.  
  3580.  
  3581.  
  3582.  
  3583.  
  3584.  
  3585.  
  3586.  
  3587.  
  3588.  
  3589.                    19 CSADD
  3590.  
  3591.  
  3592. 19.1 Source
  3593.  
  3594. This is a demonstration database for storing addresses.
  3595. It gives an adequate impression of what this library was designed for.
  3596. No complex client/server approach but strait forward functions to read
  3597. and write records.
  3598. The user interface is written with the aid of the CSA-library.
  3599.  
  3600. The source consists of two files: 'csadd.cpp'  for the user-interface and
  3601. 'csaddio.cpp' for the database.
  3602.     - 'csaddio.cpp' is generated by the CSDBGEN utility with the file
  3603.     'csaddio.def' as input.
  3604.     - 'csadd.cpp' is 'hand coded'. The file is about 500 lines.
  3605.  
  3606.  
  3607. 19.2 Openings screen
  3608.  
  3609. This is how it is supposed to look:
  3610.  
  3611.  
  3612.  eXit  Insert  Delete  Edit  Sort order  Output  Utilities  Setup    Help=F1
  3613. ┌──────────────────────────────────────────────────────────────────────────────┐
  3614. │      ╔══════════════════════ Address DataBase ═══════════════════════╗       │
  3615. │      ║                      Updated:  09/29/94   ║       │
  3616. │      ║                                   ║       │
  3617. │      ║     Name:                   City:               ║       │
  3618. │      ║     Roberta Grundburg           Kopenhagen           ║       │
  3619. │      ║                                   ║       │
  3620. │      ║     Address:               Telephone:           ║       │
  3621. │      ║     23 Grondlsy               0978-234-56756           ║       │
  3622. │      ║                                   ║       │
  3623. │      ║     Zip code:               Country:            ║       │
  3624. │      ║     TY 2347               Denmark               ║       │
  3625. │      ║                                   ║       │
  3626. │      ║     Birthday:               Relation:           ║       │
  3627. │      ║     12/04/1977               45               ║       │
  3628. │      ║                                   ║       │
  3629. │      ║     Info:                               ║       │
  3630. │      ║                                   ║       │
  3631. │      ╚═══════════════════════════════════════════════════════════════╝       │
  3632. │  ┌───────────────────────────────────────────────────────────────────────┐   │
  3633. │  │    Command: rob                     Record 243/243       │   │
  3634. │  └───────────────────────────────────────────────────────────────────────┘   │
  3635. └──────────────────────────────────────────────────────────────────────────────┘
  3636.  
  3637.  
  3638.  
  3639. 19.3 Features
  3640.  
  3641. This simple demonstration database has already some interesting
  3642. features:
  3643.     - Incremental search. That is, it 'zero's in' on the name you are
  3644.     looking for with every key entered. Normally it finds the
  3645.     required record after only two or three characters.
  3646.     - Exporting to a dBASE compatible file. The files used by the
  3647.     application are not in the dBASE format, but they can be
  3648.     exported to a dBASE compatible file.
  3649.     - Indexing also on substrings. Contrary to the traditional database,
  3650.     this one is capable of locating a record by searching for a
  3651.     substring of the key field, rather then the entire field.
  3652.  
  3653.  
  3654.  
  3655.  
  3656.  
  3657.  
  3658.  
  3659.  
  3660.  
  3661.  
  3662.  
  3663.  
  3664.  
  3665.                     Part
  3666.  
  3667.                     Five
  3668.  
  3669.  
  3670.  
  3671.  
  3672.  
  3673.  
  3674.  
  3675.  
  3676.  
  3677.  
  3678.  
  3679.  
  3680.  
  3681.  
  3682.  
  3683.  
  3684.  
  3685.  
  3686.  
  3687.  
  3688.  
  3689.  
  3690.      Part Five discusses the classes and functions implemented in the
  3691.                   CSA-library.
  3692.      They have nothing to do with databases so you can use or ignore
  3693.                   them at will.
  3694.         However, two chapters may require some attention.
  3695.      Alloc-logging which deals with heap corruption and memory leaks.
  3696.      The HEAP class for efficiently allocating large numbers of small
  3697.                   blocks.
  3698.  
  3699.  
  3700.  
  3701.                   20 CSTOOLS
  3702.  
  3703. 20.1 Introduction
  3704.  
  3705. A collection of odds & ends, merely intended to support the other
  3706. classes, but if you see something to your liking, please feel free to use
  3707. it.
  3708.  
  3709. The function prototypes are in cstools.h.
  3710.  
  3711. int add_path(char *filen,char *path);
  3712.         Adds path 'path' to filename 'filen'. Afterwards 'filen'
  3713.         contains the new name. It returns TRUE if successful,
  3714.         FALSE otherwise.
  3715. void box(int row,int col,int h,int w,int border,int color);
  3716.         Draws a box on the screen. (Non graphical.)
  3717.         row:    top row
  3718.         col:    left column
  3719.         h:    height
  3720.         w:    width
  3721.         border: type of border
  3722.             BORDER_NONE, BORDER_SPACE
  3723.             BORDER_SINGLE, BORDER_DOUBLE
  3724.         color:    text ATTRIBUTE of the border line.
  3725. int  csrand(long int);
  3726. long csrand(long amount);
  3727.         Returns a VERY random number in the range
  3728.         0..(amount-1), including both 0 and (amount-1).
  3729. int cstmpname(char *name);
  3730.         Generates the name of a non-existing file in the
  3731.         'temp' directory. It first searches for the environment
  3732.         variable 'TMP' and if not found for 'TEMP'. A filename
  3733.         is generated which does not already exist in this
  3734.         directory. The function has to be called with a
  3735.         parameter 'name' pointing to a buffer large enough to
  3736.         hold the complete drive, path and filename. If non of
  3737.         the evironment variables exist, a filename for the
  3738.         current directory is produced. It only generates a
  3739.         filename, no file is actually created. The function
  3740.         returns TRUE if a unique filename was found, FALSE
  3741.         otherwise.
  3742. int disk(char *s);
  3743.         Sets the current drive and path as indicated by string
  3744.         's'. If 's' is the empty string, 's' is set to the current
  3745.         drive and path! It returns TRUE if successful, FALSE
  3746.         otherwise.
  3747. void empty_kb(void);
  3748.         Empties the keyboard buffer.
  3749. int file_exist(char *fnaam);
  3750.         Returns TRUE if file 'fnaam' exists.
  3751. char *file_ext(char *name,char *ext);
  3752.         Adds an extension to filename 'name'. It returns a
  3753.         pointer to an internal buffer which contains the new
  3754.         name. If 'name' already has an extension, it is
  3755.         overwritten. The string 'name' itself is not changed!
  3756. long filesize(char *name);
  3757.         Returns the size of file 'name'.
  3758. void filter_string(char *source,char *allowed);
  3759.         All the characters in 'source' which are not in
  3760.         'allowed' are removed from 'source'.
  3761. void gotoyx(int y,int x);
  3762.         Same as Borlands gotoxy(x,y) but with reversed
  3763.         parameters.
  3764. int is_color(void);
  3765.         Returns TRUE if you are using a color screen.
  3766.         FALSE otherwise.
  3767. void lower_upper(char *ptr);
  3768.         Converts the entire string to upper case.
  3769. long lrandom(long amount);
  3770.         Returns a long random number in the range
  3771.         0..(amount-1), including both 0 and (amount-1).
  3772. int make_color(int fgc,int bgc);
  3773.         Returns the text attribute corresponding with the Fore
  3774.         Ground Color (fgc) and the Back Ground Color (bgc).
  3775. size_t next_prime(size_t pri);
  3776.         Calculates next higher prime number.
  3777. char *notabs(char *s);
  3778.         Replaces every occurrence of a tab character in 's'
  3779.         with a single space. That is: tabs are not expanded,
  3780.         but simply removed.
  3781. char *remove_space(char *s);
  3782.         Removes ALL the blanks from the string 's'. It returns
  3783.         character pointer 's'.
  3784. unsigned int  sqrti(unsigned int n);
  3785. unsigned long sqrtl(unsigned long n);
  3786.         Calculates the sqrt from n WITHOUT USING
  3787.         FLOATING POINT arithmetic.
  3788. void str_split(char *source,char ch,char *first,char *last);
  3789.         Split 'string' source at the first occurrence of character
  3790.         'ch'. Ch is included in neither the 'first' nor the 'last'
  3791.         string.
  3792. void str_strip(char *source,char *remove);
  3793.         Characters in 'source' which are also in 'remove' are
  3794.         removed from 'source'.
  3795. int str_equal(char *s1, char *s2);
  3796.         Returns TRUE if 's1' is equal to 's2', discriminating
  3797.         between upper and lower case.
  3798. void str_left(char *source,char *dest,int len);
  3799.         Copies at most 'len' number of characters from the
  3800.         left of 'source' to 'dest'.
  3801. char *string_replace_ones(char *source,char *d,char *r);
  3802.         Replaces the first occurrence of 'd' in 'source' with 'r'.
  3803. int string_replace(char *s,char *d,char *r);
  3804.         Replaces every occurrence of 'd' in 'source' with 'r'. It
  3805.         returns an integer number indicating the number of
  3806.         times a substitution was made.
  3807. long time_stamp(void);
  3808.         Returns a higher long number on each successive
  3809.         call, starting with zero again when MAXLONG is
  3810.         reached.
  3811. void trim_string(char *s);
  3812.         Removes heading and trailing blanks from string 's'.
  3813. void wait(long msec);
  3814.         Waits 'msec' milliseconds.
  3815. void waitkb(long msec);
  3816.         Waits 'msec' milliseconds or until the next keyboard
  3817.         hit.
  3818.  
  3819.                   21 CSKEYS
  3820.  
  3821.  
  3822. Almost all the input for the library functions is done through the cskey()
  3823. function.
  3824.  
  3825. Syntax:
  3826.     int cskey(void);
  3827.  
  3828. The return value can be one of the following: ( defined in CSKEYS.H )
  3829.  
  3830.  
  3831.      CTRL_A    KEY_A    KEY_a      ALT_A     DELETE  CURSOR_UP
  3832.      CTRL_B    KEY_B    KEY_b      ALT_B     END     CURSOR_DOWN
  3833.      CTRL_C    KEY_C    KEY_c      ALT_C     HOME    CURSOR_RIGHT
  3834.      CTRL_D    KEY_D    KEY_d      ALT_D     PAGE_UP CURSOR_LEFT
  3835.      CTRL_E    KEY_E    KEY_e      ALT_E     PAGE_DOWN
  3836.      CTRL_F    KEY_F    KEY_f      ALT_F     INSERT
  3837.      CTRL_G    KEY_G    KEY_g      ALT_G     BACKSPACE
  3838.      CTRL_H    KEY_H    KEY_h      ALT_H     TAB
  3839.      CTRL_I    KEY_I    KEY_i      ALT_I     SHIFT_TAB
  3840.      CTRL_J    KEY_J    KEY_j      ALT_J     ENTER
  3841.      CTRL_K    KEY_K    KEY_k      ALT_K     ESC
  3842.      CTRL_L    KEY_L    KEY_l      ALT_L     SPACE
  3843.      CTRL_M    KEY_M    KEY_m      ALT_M
  3844.      CTRL_N    KEY_N    KEY_n      ALT_N     CTRL_DELETE
  3845.      CTRL_O    KEY_O    KEY_o      ALT_O     CTRL_HOME
  3846.      CTRL_P    KEY_P    KEY_p      ALT_P     CTRL_CURSOR_UP
  3847.      CTRL_Q    KEY_Q    KEY_q      ALT_Q     CTRL_CURSOR_DOWN
  3848.      CTRL_R    KEY_R    KEY_r      ALT_R     CTRL_CURSOR_RIGHT
  3849.      CTRL_S    KEY_S    KEY_s      ALT_S     CTRL_CURSOR_LEFT
  3850.      CTRL_T    KEY_T    KEY_t      ALT_T     CTRL_PAGE_UP
  3851.      CTRL_U    KEY_U    KEY_u      ALT_U     CTRL_PAGE_DOWN
  3852.      CTRL_V    KEY_V    KEY_v      ALT_V     CTRL_END
  3853.      CTRL_W    KEY_W    KEY_w      ALT_W
  3854.      CTRL_X    KEY_X    KEY_x      ALT_X
  3855.      CTRL_Y    KEY_Y    KEY_y      ALT_Y
  3856.      CTRL_Z    KEY_Z    KEY_z      ALT_Z
  3857.  
  3858.      F1     SHIFT_F1    CTRL_F1   ALT_F1    KEY_1   ALT_DELETE
  3859.      F2     SHIFT_F2    CTRL_F2   ALT_F2    KEY_2   ALT_HOME
  3860.      F3     SHIFT_F3    CTRL_F3   ALT_F3    KEY_3   ALT_CURSOR_UP
  3861.      F4     SHIFT_F4    CTRL_F4   ALT_F4    KEY_4   ALT_CURSOR_DOWN
  3862.      F5     SHIFT_F5    CTRL_F5   ALT_F5    KEY_5   ALT_CURSOR_RIGHT
  3863.      F6     SHIFT_F6    CTRL_F6   ALT_F6    KEY_6   ALT_CURSOR_LEFT
  3864.      F7     SHIFT_F7    CTRL_F7   ALT_F7    KEY_7   ALT_PAGE_UP
  3865.      F8     SHIFT_F8    CTRL_F8   ALT_F8    KEY_8   ALT_PAGE_DOWN
  3866.      F9     SHIFT_F9    CTRL_F9   ALT_F9    KEY_9   ALT_END
  3867.      F10    SHIFT_F10    CTRL_F10  ALT_F10   KEY_0
  3868.      F11    SHIFT_F11    CTRL_F11  ALT_F11
  3869.      F12    SHIFT_F12    CTRL_F12  ALT_F12
  3870.  
  3871. The predefined values for the 'normal' keys like 'A', 'a' or '1'
  3872. are the same as the ASCII values. This means you are not
  3873. forced the type things like
  3874.  
  3875.         if( KEY_A==cskey() ) ....
  3876.  
  3877.     but can also use:
  3878.  
  3879.         if( 'A'==cskey() )  ......
  3880.  
  3881.  
  3882. 21.1 CSKEYS.exe
  3883.  
  3884. There is also a simple utility to test the return value of the cskeys()
  3885. function.
  3886.  
  3887. This is cskeys.
  3888.  
  3889. With this it becomes very easy to make your own additions to the
  3890. predefined keys in 'cskeys.h'.
  3891.  
  3892.  
  3893.                    22 HEAP
  3894.  
  3895.  
  3896. 22.1 Purpose
  3897.  
  3898. To avoid having to allocate many small blocks, a special HEAP class is
  3899. implemented. The idea is to do allocations in chunks of about 2Kb and
  3900. take the small amounts from that when needed.
  3901.  
  3902. This approach has considerable advantages.
  3903.     - You can release all allocated memory with just one function call
  3904.     instead of freeing many small blocks separately.
  3905.     - It is a lot faster because normal heap operations are relatively
  3906.     slow.
  3907.     - Heap efficiency is also improved. It is much easier for the heap to
  3908.     deal with relatively few allocations of about 2Kb then it is to
  3909.     deal with numerous small allocations.
  3910.     - It can save valuable memory. There is considerable overhead
  3911.     involved in using the heap. Apart from what you need, several
  3912.     additional bytes are used to 'pointer' the allocated blocks
  3913.     together. In addition, allocations are done in multiples of 16
  3914.     bytes. This can lead to a situation where you need only 13
  3915.     bytes while 32 bytes are used!
  3916.  
  3917.  
  3918. 22.2 When to use it?
  3919.  
  3920. The HEAP class is particularly useful when dealing with pointer
  3921. structures in ram. Pointer structures are small, all of the same size and
  3922. an application will probably use a lot of them.
  3923. The BUFFER class described earlier in this documentation also uses
  3924. the HEAP class. This means you can use it without enlarging your
  3925. application.
  3926. The HEAP class assumes allocations of a fixed size. This limits its
  3927. usefulness but improves efficiency. It is very well possible to use more
  3928. then one instance of the HEAP class in an application. It is feasible to
  3929. use a different HEAP for every size of allocation needed.
  3930. The class was designed with small allocations in mind, something
  3931. below 50 bytes. It is doubtful whether the HEAP class still makes sense
  3932. for allocations above 100 bytes.
  3933.  
  3934. Summarizing:
  3935. - Allocations have to be of a fixed size.
  3936. - Allocations have to be small, below 50 bytes.
  3937. - Many allocations of this type are going to take place.
  3938.  
  3939.  
  3940. 22.3 Using HEAP.
  3941.  
  3942. Using the HEAP class starts of with an initialization, stating the size of
  3943. the allocations. Afterwards the class has to be 'opened'. From there on
  3944. allocations can be made, and blocks can be free-ed again. When the
  3945. work is done, the close or the zap function can be called to free all
  3946. allocated memory.
  3947.  
  3948.  
  3949.  
  3950. // Example
  3951.  
  3952. #include "csheap.h"
  3953.  
  3954. void main(void)
  3955. {
  3956.     typedef struct
  3957.     {
  3958.     void *next;
  3959.     void *prev;
  3960.     int  number;
  3961.     } pStruct;            // A typical pointer structure.
  3962.  
  3963.     HEAP heap;            // HEAP class instance.
  3964.  
  3965.     heap.init(sizeof(pStruct)); // Initialize it for the size of the
  3966.                 // pointer structure.
  3967.  
  3968.     heap.open();        // Open the class so it can be used.
  3969.  
  3970.     pStruct *p,*q;
  3971.  
  3972.     p=(pStruct *)heap.malloc(); // Allocation.
  3973.     q=(pStruct *)heap.malloc(); // Allocation.
  3974.  
  3975.     p.next=q.prev=NULL;     // Doing something.
  3976.  
  3977.     // Doing much more.
  3978.  
  3979.     heap.free(q);        // Freeing q.
  3980.  
  3981.     heap.close();        // Finally finished.
  3982.                 // Freeing all allocated memory.
  3983.  
  3984. }
  3985.  
  3986.  
  3987.  
  3988.  
  3989. 22.4 Functions in alphabetical order.
  3990.  
  3991. The function prototypes are in CSHEAP.H.
  3992.  
  3993. void close(void);
  3994.         Closes the class. All allocated memory is freed. The
  3995.         initialisation parameters are retained, which makes it
  3996.         possible to reopen the class without calling init(). This
  3997.         function is also called by the class destructor.
  3998. void empty(void );
  3999.         Frees all allocated memory, but the class remains
  4000.         open.
  4001. void init(U16 alloc_size,U16 page_size=2048);
  4002.         Initializes the class. 'Alloc_size' is the size of the
  4003.         allocations needed. 'Page_size' is the size of the
  4004.         chunks which are going to be allocated from the
  4005.         heap. This parameter has a default value of 2048
  4006.         bytes.
  4007. int open(void); Opens the class. The 'init()' function has to be called
  4008.         first. The function returns TRUE on success and
  4009.         FALSE otherwise.
  4010. void free(void *p);
  4011.         Frees the previously allocated block 'p' is pointing at.
  4012. void *malloc(void);
  4013.         Allocates a block and returns a pointer to it. If no
  4014.         memory is available, a NULL pointer is returned.
  4015. void zap(void); Frees all allocated memory and closes the class. The
  4016.         initialization parameters set by the init() function are
  4017.         reset. This means the class has to be initialized again
  4018.         before it can be reopened.
  4019.  
  4020.  
  4021.                    23 Alloc-Logging
  4022.  
  4023. 23.1 Introduction
  4024.  
  4025. Dynamic memory allocations can create problems which are difficult to
  4026. trace. Therefore, this library contains a set of functions which can be
  4027. used to replace the normal malloc() and free() functions. The
  4028. replacements can be made to write a record to a log. This log can be
  4029. used later to check for memory leaks.
  4030.  
  4031. The replacements also test for things like freeing a NULL pointer or a
  4032. malloc which returns NULL. In the DOS version, Borlands 'heapcheck'
  4033. functions are called to test for heap integrity.
  4034.  
  4035. Replacements are preprocessor commands which can be switched on
  4036. and off with the preprocessor variable CS_DEBUG.
  4037. If CS_DEBUG is not defined, the normal functions are called.
  4038.  
  4039. 23.2 Replacements
  4040.  
  4041. Replacements are available for the following functions:
  4042. Prototypes in csmalloc.h.
  4043.  
  4044.    Function:            Replacement:
  4045.     malloc            csmalloc
  4046.     calloc            cscalloc
  4047.     realloc            csrealloc
  4048.     free            csfree
  4049.     farmalloc            csfarmalloc
  4050.     farcalloc            csfarcalloc
  4051.     farrealloc            csfarrealloc
  4052.     farfree            csfarfree
  4053.  
  4054. The use of the replacements is fully equivalent to the original.
  4055.  
  4056. The allocations in the CS-libraries are always done by calling the
  4057. replacements. The production version of the libraries was compiled
  4058. without CS_DEBUG being defined, so the normal functions are used
  4059. and are called without any additional overhead. When the debug
  4060. version was compiled, CS_DEBUG was defined and as a result all the
  4061. allocations done by the library functions can be logged!
  4062.  
  4063.  
  4064. 23.3 Logging
  4065.  
  4066. Logging of allocations can be switched on and off through the use of
  4067. two functions.
  4068.  
  4069. void alloc_logging(int TrueFalse);
  4070.         After a call to alloc_logging(TRUE) all the allocations
  4071.         are logged in the ASCII file 'malloc.log'. Calling
  4072.         alloc_logging(FALSE) switches the logging off.
  4073. void alloc_logging(int TrueFalse,char *name);
  4074.         This is basically the same as the previous function
  4075.         but has the additional option of specifying the name
  4076.         of the log file.
  4077.  
  4078. The next example displays a part of an allocation log.
  4079.  
  4080.  
  4081.  
  4082.  4E79:0004       file csedst30.cpp    line 8: malloc()    8 bytes
  4083.  4E7A:0004       file csedst30.cpp    line 8: malloc()    8 bytes
  4084.  4E78:0004       file csedst30.cpp  line 23: free()
  4085.  4E78:0004       file csedst30.cpp    line 8: malloc()    9 bytes
  4086.  4E79:0004       file csedst30.cpp  line 23: free()
  4087.  4E7B:0004       file csedst30.cpp    line 8: malloc()    22 bytes
  4088.  4E7B:0004       file csedst28.cpp  line 12: realloc free()
  4089.  4E7B:0004       file csedst28.cpp  line 12: realloc malloc()
  4090.  4E7A:0004       file csedstr.cpp  line 15: free()
  4091.  4E7B:0004       file csedstr.cpp  line 15: free()
  4092.  
  4093.  
  4094.  
  4095.  
  4096. As can be seen, the first column displays the pointer involved, the
  4097. second and third display the file and the line where the call was made.
  4098. When an allocation is concerned its size is also displayed. Reallocs
  4099. appear as two lines.
  4100.  
  4101.  
  4102. 23.4 Memory Leaks.
  4103.  
  4104. With a log like this it is easy to check for memory leaks. In fact, a
  4105. command-line utility is supplied to check for that. It is called
  4106. CSMALLOC. Only one parameter needs to be supplied: the name of
  4107. the allocation log.
  4108.  
  4109. Example
  4110.  
  4111. c:\test>CSMALLOC malloc.log
  4112.  
  4113.  
  4114.  
  4115. If it encounters a malloc which is not matched by a free, it displays the
  4116. pointer involved.
  4117. Like:
  4118.  
  4119.  UNMATCHED address: 29CC:0004
  4120.  
  4121.  
  4122.  
  4123. If all malloc's are matched by a free it says something like this:
  4124.  
  4125.   NO ERRORS encountered!!
  4126.  
  4127.  
  4128.   Number of addresses: 23
  4129.   Lowest address:  29CC:0004
  4130.   Highest address: 2EAE:0004
  4131.  
  4132.  
  4133.  
  4134. If malloc logging is kept on for longer periods, the log file can become
  4135. extremely large. However, this poses no problem for CSMALLOC.
  4136.  
  4137. If you are planning to use this method to detect memory
  4138. leaks, it is essential to switch on the logging before the first
  4139. allocation is done. Don't forget class constructors do
  4140. allocations as well!
  4141.                   24 CSEDSTR
  4142.  
  4143.  
  4144. The class for manipulating strings. Instead of providing the formal
  4145. syntax we will clarify things by supplying a large number of examples.
  4146.  
  4147. Class name: EDSTR
  4148. Prototypes are in CSEDSTR.H.
  4149.  
  4150.  
  4151.    #include "csedstr.h"
  4152.  
  4153.    main(void)
  4154.    {
  4155.       EDSTR str;
  4156.       str=" A test ";       // Assign a string
  4157.       str.upper();        // Convert to upper case
  4158.       str.lower();        // Convert to lower case
  4159.       str.trim();        // Remove all leading and trailing blanks
  4160.                 // str contains now: "a test";
  4161.       str+=" At the end ";  // APPEND at the end
  4162.                 // str contains now: "a test At the end"
  4163.       int i=-345;
  4164.       str=i;            // Convert the integer value to string
  4165.                 // str contains now: "-345";
  4166.       str="1001";
  4167.       i=str;            // Assign string to integer
  4168.       str="A line";
  4169.       str.strip("ijkl");    // Stripping the characters i,j,k,l from
  4170.                 // str.
  4171.                 // Str now contains: "A ne";
  4172.       str="A line";
  4173.       str.filter("ijkl");   // Allow only the characters i,j,k,l in
  4174.                 // str.
  4175.                 // Str now contains: "li";
  4176.       str="The quick brown fox";
  4177.       str[4]='Q';           // Str now contains: "The Quick brown fox"
  4178.  
  4179.       EDSTR str2="by C++ !";
  4180.       str="Made possible ";
  4181.       str=str+str2;        // Str: "Made possible by C++ !";
  4182.  
  4183.       if( str<str2)   ..
  4184.       if( str>str2)   ..
  4185.       if( str<=str2)  ..
  4186.       if( str>=str2)  ..
  4187.       if( str==str2)  ..    // Comparisons are possible.
  4188.                 // Case is always ignored.
  4189.        gotoxy(5,20); clreol();
  4190.        str.edit(15,25); // User can edit the string.
  4191.             // Only 15 characters are displayed.
  4192.             // The maximal length of the string
  4193.             // is 25 characters.
  4194.             // The string will scroll if it
  4195.             // becomes longer then 15 characters.
  4196.             // 'Enter' or 'Escape' will
  4197.             // terminate the function.
  4198.   }
  4199.                  25 CSWINDOWS
  4200.  
  4201. 25.1 Introduction
  4202.  
  4203. The WINDOW class is an implementation of the well known
  4204. character-based text windows.
  4205.  
  4206. The window toolbox can be used in two distinct ways:
  4207.     1) through the use of 'old-fashioned' C functions.
  4208.     2) as a C++ class.
  4209.  
  4210. The member functions of the WINDOW class are fine for manipulating
  4211. one instance of the class, but    the C-functions seem to have the
  4212. advantage when dealing with more then one instance.
  4213. E.g. shifting from one window to another or removing all windows at
  4214. once involves more then one instance of the WINDOW class, so this is
  4215. done by C-functions rather then class member functions.
  4216.  
  4217. The examples above already gives you an impression of which
  4218. functions to use when. When you are dealing with ONE window use the
  4219. class, in all other cases use the global C functions.
  4220. For the sake of completeness, the syntax of all the C-style functions is
  4221. given, but whenever possible use the class member functions.
  4222.  
  4223. For those who are becoming nervous:
  4224.     - You normally will need only two very simple C functions.
  4225.     - A few examples will make things clear!
  4226.  
  4227.  
  4228. 25.2 General Information
  4229.  
  4230. Class name: WINDOW
  4231. Prototypes are in CSWINDOW.H.
  4232.  
  4233.     - Every window is uniquely identified by a positive integer number.
  4234.  
  4235.     - In practice the number of windows an application can use is only
  4236.     limited by the available amount of memory.
  4237.  
  4238.     - Windows can 'overlay' each other. When an underlying window is
  4239.     called to be brought to the top, some flickering may appear
  4240.     because the still overlying windows must first be removed, and
  4241.     later be replaced.
  4242.  
  4243.     - Checks are made to see if the window which has to be brought to
  4244.     the top is overlaid. If not, it will become immediately active.
  4245.  
  4246.     - The windows are 'chained' together. The windows which are used
  4247.     last are closest to the end of the chain. When you are worried
  4248.     about performance:
  4249.         a) try not to activate a window which is overlaid,
  4250.         b) use only windows close to the end of the chain.
  4251.     However, under normal circumstances you will never have to
  4252.     worry about performance, because the window functions are
  4253.     very fast.
  4254.  
  4255.  
  4256. 25.3 The C++ version, the class WINDOW
  4257.  
  4258.  
  4259. //  Example:
  4260.  
  4261.   #include "dos.h"
  4262.   #include "cswindow.h"
  4263.  
  4264.   main(void)
  4265.   {
  4266.     WINDOW demo;        // Declare a window
  4267.  
  4268.     demo.height(10);        // The number of lines
  4269.     demo.width(40);        // The number of columns
  4270.     demo.head(" A Demo Window ");// A text in the border
  4271.     demo.shadow(SHADOW);     // Make a shadow
  4272.     demo.activate();         // Display the window
  4273.  
  4274.     gotoxy(5,5);         // Write the famous
  4275.     cprintf(" Hello World !! "); // words in the window.
  4276.  
  4277.     waitkb(5000);          // Wait 5 seconds.
  4278.  
  4279.   }
  4280.  
  4281.  
  4282.  
  4283.  
  4284. 25.3.1 Syntax of the MEMBER functions
  4285.  
  4286. void top(int)    Sets the top row of the window. If you enter -1 the
  4287.         window is centered vertically on the screen.
  4288.         Default is -1.
  4289. void left(int)        Sets the left column if the window. If you enter -1 the
  4290.             window is centered horizontally on the screen.
  4291.         Default is -1.
  4292. void height(int)    Sets the height of the window.
  4293.         Default is 24.
  4294. void width(int) Sets the width of the window.
  4295.         Default is 80.
  4296. void set_dim(int top,int left,int height,int width)
  4297.         This set all four at once with this function.
  4298. void border(int)    Sets the border type. Four types are pre-defined in
  4299.             the header file CSWINDOW.H.
  4300.         1: W_BORDER_NONE    No border.
  4301.         2: W_BORDER_SINGLE  Border is a single line.
  4302.         3: W_BORDER_DOUBLE  Border is a double line.
  4303.         4: W_BORDER_SPACE   Border made out of 'space'
  4304.                     is drawn around the
  4305.                     window.
  4306.         The default is BORDER_SINGLE.
  4307. void head(char *)
  4308.         Sets the heading text of the window. This text is at
  4309.         center of the top of the window, but only if a border is
  4310.         The maximum length of this string is 49 characters.
  4311.         The default is the empty string.
  4312. void shadow(int)
  4313.         A value of 0 means no shadow, any other value will
  4314.         create a shadow. In CSWINDOW.H are two values
  4315.         pre-defined.
  4316.         1: NO_SHADOW    Don't display shadow.
  4317.         2: SHADOW    Display shadow.
  4318.         The default is NO_SHADOW.
  4319. void activate(void)
  4320.         This makes the window appear on the screen, on top
  4321.         of all other windows. The first time it will also create
  4322.         the window. If the window already exists, but is lying
  4323.         beneath other windows, it is shifted to the top.
  4324. void border_color(int)
  4325. void screen_color(int)
  4326.         Sets the text-attribute of the border and the text
  4327.         screen. Notice: the text ATTRIBUTE. This means
  4328.         both the foreground and the background colors are
  4329.         set. This is implemented through a call to Borland's
  4330.         TEXTATTR() function. See their documentation for
  4331.         more information. You can also use the
  4332.         'make_color()' function defined in 'cstools'.
  4333. int border_color(void)
  4334.         Returns the text-attributes of the border.
  4335. int screen_color(void)
  4336.         Returns the text-attributes of the screen.
  4337. void clear(void)    Clears the text screen.
  4338.         This is done automatically when the window is first
  4339.         created.
  4340. void remove(void)
  4341.         Remove the window permanently. The previous
  4342.         active window will become the active window again.
  4343. void remove_all(void)
  4344.         Removes ALL windows.
  4345. int adjust(void)    Even if the window already exists and is visible on
  4346.             the screen, you can make changes. Just call the
  4347.             appropriate functions ( e.g. height() to change the
  4348.             height etc.) and when you are done call 'adjust()'. The
  4349.             window will then change accordingly. The function
  4350.             returns TRUE if successful FALSE otherwise.
  4351. int previous(void)
  4352.         Returns to the previous active window. That is: the
  4353.         window that was active before the current window
  4354.         became active. The function returns TRUE if
  4355.         successful FALSE otherwise.
  4356. int user_adjust(void)
  4357.         This function gives the application user control over
  4358.         the window. He/she can change the position of the
  4359.         window with the cursor keys and the size through use
  4360.         of the control-cursor keys. The function ends when
  4361.         ENTER is pressed. The function returns TRUE if
  4362.         successful FALSE otherwise.
  4363. void auto_delete(int)
  4364.         Sets the auto delete option. If called with a value
  4365.         unequal to 0, the window will be removed if the class
  4366.         instance is destructed. Otherwise the window will
  4367.         remain on the screen even if the class instance no
  4368.         longer exists. The default is ON.
  4369. void scroll(int ROW,int COL)
  4370.         Make the text in the window scroll.
  4371.         ROW:    scrolling up/down. A positive value means
  4372.             up (e.g. line 2 will become line 1).
  4373.         COL:    scrolling left/right. A positive value means to
  4374.             the right (e.g. column 1 will become
  4375.             column 2).
  4376. void get_dim(int *row,int *col,int *h,int *w)
  4377.         Returns the size-related-parameters of the window.
  4378.         The values returned do include the border but NOT
  4379.         the shadow.
  4380.         *row:    Top row.
  4381.         *col:    Left column
  4382.         *h:    height
  4383.         *w:    width
  4384.         These values need NOT be the same as the ones
  4385.         you assigned, because the window is adjusted to the
  4386.         limitations of the screen. (e.g. if you set height to 50,
  4387.         this function will tell you it is 25. )
  4388. void get_in_dim(int *row,int *col,int *h,int *w)
  4389.         The same as the previous function but now the
  4390.         returned values do NOT include the border and do
  4391.         NOT include any shadow. So, the inner dimensions
  4392.         are returned.
  4393. void work_size(int *height,int *width)
  4394.         Same as the previous function, but only the height
  4395.         and the width are returned.
  4396. int number(void)
  4397.         Returns the number of the window. Only needed if
  4398.         you are using the C functions as well.
  4399. 25.4 The C version
  4400.  
  4401. As stated before, every window is identified by a unique integer
  4402. number. In the C++ version you don't have to worry about this number.
  4403. In the C version however, it is of prime importance. If a function has
  4404. parameters, the first parameter is always the number of the window you
  4405. are referring to.
  4406.  
  4407. As pointed out in the introduction you are supposed to use the class
  4408. functions whenever possible. In fact there are only two functions of the
  4409. C version you should use.
  4410.  
  4411. These are:
  4412.  
  4413. int win_current(void);
  4414.         Returns the number of the current active window.
  4415.         You might need this number if you want to return to
  4416.         this window somewhere later on in your application.
  4417. int win_shift(int num);
  4418.         Make window 'num' the active window. Useful in
  4419.         combination with the previous function.
  4420.  
  4421.  
  4422. In rare cases:
  4423.  
  4424. void win_remove_all(void);
  4425.         Remove all windows.
  4426. int win_default(void);
  4427.         For writing outside any existing window.
  4428.  
  4429. 25.4.1 Example
  4430.  
  4431. Problem:
  4432. You want to write an error handling function which writes a message at
  4433. the bottom line of the screen and, after some waiting, returns to the
  4434. original window and continues. The problem is, the function can be
  4435. called from 'anywhere' and at the moment you are writing the function,
  4436. it is not clear to which window to return.
  4437.  
  4438.  
  4439.  
  4440. #include <......>
  4441.  
  4442. WINDOW w_error;         // Window for the messages, global...
  4443.  
  4444. void disp_error(char *s)
  4445. {
  4446.     int old_window=win_current();   // The window the function
  4447.                 // is called from.
  4448.     w_error.activate();     // Make the error window
  4449.                 // the active window.
  4450.     cprintf("\n\r %s ",s);      // Print the text.
  4451.     wait(2500);         // Wait 2.5 seconds.
  4452.     win_shift(old_window);    // Return to the original window!
  4453. }
  4454.  
  4455. main(void)
  4456. {
  4457.     w_error.set_dim(23,1,3,80);
  4458.     w_error.head(" E r r o r s ");
  4459.     w_error.activate();     // The window permanent visible
  4460.                 // A lot of other windows
  4461.                 // The program calls.
  4462. }
  4463.  
  4464.  
  4465. Note:    In this simple example the 'previous' function also would have
  4466.     solved the problem. In more complicated cases however, this
  4467.     method can very well be the only solution.
  4468.  
  4469.  
  4470. 25.5 Syntax of the C functions
  4471.  
  4472. int win_make(    int& num,
  4473.         int border_color,
  4474.         int screen_color,
  4475.         char *head,
  4476.         int top,
  4477.         int left,
  4478.         int height,
  4479.         int width,
  4480.         int border,
  4481.         int shadow);
  4482.  
  4483.  
  4484. Parameters:
  4485.         num The number of the new window. If a window
  4486.             with this number already exists it is deleted.
  4487.             In the header file CSWINDOW.H is
  4488.             predefined W_NEW. If you call the function
  4489.             with 'num' equal to W_NEW a new window
  4490.             is created and num is changed into a
  4491.             number which was formerly not used. To
  4492.             make this possible num is passed by
  4493.             reference.
  4494.         border_color
  4495.         screen_color
  4496.             Sets the text-attribute of the border and the
  4497.             text screen.
  4498.             Notice: the text ATTRIBUTE. This means
  4499.             both the foreground and the background
  4500.             colors are set. This is implemented through
  4501.             a call to Borland's TEXTATTR() function.
  4502.             See their documentation for more
  4503.             information.
  4504.         head    Sets the heading text of the window. This
  4505.             text is displayed at the center of the top of
  4506.             the window, but only if a border is present.
  4507.         top    Sets the top row of the window. If you enter
  4508.             -1 the window is centered vertically on the
  4509.             screen.
  4510.         left        Sets the left column if the window. If you
  4511.                 enter -1 the window is centered horizontally
  4512.                 on the screen.
  4513.         height    Sets the height of the window.
  4514.         width    Sets the width of the window.
  4515.         border    Sets the border type. Four types are
  4516.             predefined in the header file CSWINDOW.H.
  4517.             1: W_BORDER_NONE    No border.
  4518.             2: W_BORDER_SINGLE  Border is a single
  4519.                         line.
  4520.             3: W_BORDER_DOUBLE  Border is a
  4521.                         double line.
  4522.             4: W_BORDER_SPACE   Border made out
  4523.                         of 'space' is
  4524.                         drawn around the
  4525.                         window.
  4526. void win_remove(void)
  4527.         Remove the active window from the screen. The
  4528.         previously active window will become the active
  4529.         window again.
  4530. void win_remove_all(void)
  4531.         Removes ALL windows.
  4532. int  win_shift(int num)
  4533.         Will shift window with number 'num' to the top. The
  4534.         function returns TRUE if successful FALSE otherwise.
  4535. int  win_present(int num);
  4536.         Returns TRUE if window 'num' exists, FALSE
  4537.         otherwise.
  4538. int  win_first_unused(void)
  4539.         Returns the lowest positive number which is not 'in
  4540.         use' by a window.
  4541. int  win_current(void)
  4542.         Returns the number of the current active window. If
  4543.         no window is active it returns -1.
  4544. void win_clear(void)
  4545.         Clears the current active window.
  4546. int win_adjust( int num,
  4547.         int border_color,
  4548.         int screen_color,
  4549.         char *head,
  4550.         int top,
  4551.         int left,
  4552.         int height,
  4553.         int width,
  4554.         int border,
  4555.         int shadow);
  4556.         Is used to make changes to an existing window. The
  4557.         parameters are the same as with win_make(). Call
  4558.         this function with the parameters set to the newly
  4559.         desired values and your window will change
  4560.         accordingly. The function returns TRUE if successful
  4561.         FALSE otherwise.
  4562. int win_previous(void)
  4563.         Returns to the previous active window. That is: the
  4564.         window that was active before the current window
  4565.         became active. The function returns TRUE if
  4566.         successful FALSE otherwise.
  4567. int win_user_adjust(void)
  4568.         This function gives the application user control over
  4569.         the current active window. He/she can change the
  4570.         position by the cursor keys and the size by the
  4571.         control-cursor keys. The function ends when ENTER
  4572.         is pressed. The function returns TRUE if successful
  4573.         FALSE otherwise.
  4574. void win_scroll(int num, int ROW,int COL)
  4575.         Make the text in the window 'num' scroll.
  4576.         ROW:    scrolling up/down. A positive value means
  4577.             up (e.g. line 2 will become line 1).
  4578.         COL:    scrolling left/right. A positive value means to
  4579.             the right (e.g. column 1 will become
  4580.             column 2).
  4581. void win_get_dim(int num,int *row,int *col,int *h,int *w)
  4582.         Returns the size-related-parameters of window 'num'.
  4583.         The values returned do include the border but NOT
  4584.         the shadow.
  4585.         *row:    Top row.
  4586.         *col:    Left column
  4587.         *h:    height
  4588.         *w:    width
  4589.         These values need NOT be the same as the ones
  4590.         you assigned, because the window is adjusted to the
  4591.         limitations of the screen. (e.g. if you set height to 50,
  4592.         this function will tell you it is just 25. )
  4593. void win_get_in_dim(int num,int *row,int *col,int *h,int *w)
  4594.         The same as the previous function but now the
  4595.         returned values do NOT include the border and do
  4596.         NOT include any shadow. So, the inner dimensions
  4597.         are returned.
  4598. win_work_size(int num,int *height,int *width)
  4599.         Same as the previous function, but only the height
  4600.         and the width are returned.
  4601. int win_default(void)
  4602.         Not a window at all. Intended for writing outside any
  4603.         existing window. The x,y coordinates are set back to
  4604.         the full screen, as it is when you are working without
  4605.         windows. The software represents this virtual window
  4606.         by number -1. This number can also be returned by
  4607.         the win_current() function.
  4608.  
  4609. 25.6 Working within a Window
  4610.  
  4611. Working within a window is the same for both versions. All the above
  4612. mentioned functions are built around the compiler-supplied function
  4613. window(). This means you can use all Borlands I/O functions that are
  4614. intended to work relative to a window.
  4615.  
  4616. The most important ones are:
  4617.         gotoxy();   // To move the cursor
  4618.         putch();    // Displaying a character in the window
  4619.         cputs();    // Displaying a string
  4620.         delline();  // Delete a line
  4621.         insline();  // Insert a line
  4622.         clrscr();   // Clears the window
  4623.         clreol();   // Clears until end of line
  4624.         getche();   // Read a character
  4625.         cgets();    // Read a string
  4626.         cprintf();  // Window version of printf()
  4627.                 // Don't forget, you need "\n\r "
  4628.                 // to go to the start of the next line.
  4629.                 // cprintf("\n "); will put the cursor
  4630.                 // one line down, without going to the
  4631.                 // start of that line.
  4632.  
  4633.  
  4634. 25.7 File Browsing
  4635.  
  4636.  
  4637. The WINDOW class has a member funtion 'browse', which aid in
  4638. displaying help-files.
  4639.  
  4640.  
  4641. // Example
  4642.  
  4643.  
  4644.    WINDOW help;             // Create Window for help text.
  4645.    help.set_dim(-1,-1,18,70);        // Set size and position.
  4646.    help.head(" Help Screen ");      // A Header.
  4647.    help.color(HlpBorCol,HlpScrCol); // Set the colors.
  4648.    help.browse("help.txt");         // Browse the help file.
  4649.  
  4650.  
  4651.  
  4652. The help file has to be an ASCII file.
  4653.  
  4654. Supported keys:
  4655.  
  4656.     ESC and ENTER:    Exit.
  4657.     Cursor Up:        1 line up
  4658.     Cursor Down:    1 line down
  4659.     Page Up:        1 screen up.
  4660.     Page Down:        1 screen down.
  4661.     Home:        Top of file.
  4662.     End:        End of file.
  4663.  
  4664.                   26 CSMENU
  4665.  
  4666.  
  4667. 26.1 General Information
  4668.  
  4669. There are a lot of ways to implement a menu system. One very
  4670. common method concentrates on directly calling functions from within
  4671. the menu. This is not the method used here, because it seems to limit
  4672. its usefulness.
  4673.  
  4674. This menu system returns an integer value when an option is chosen.
  4675. The idea is to make the return value equal to a certain function key
  4676. connected with the option. The application user can then browse
  4677. through the menus and select an option or hit the function key directly.
  4678. In both cases your program has to deal with the same integer value
  4679. which can easily be processed by applying a 'switch' statement.
  4680.  
  4681. Examples will explain things further.
  4682.  
  4683. There is no difference between a menu and a sub-menu. The definition
  4684. is the same in both cases. The difference lies in the application of a
  4685. 'connect' function which makes one menu the sub-menu of another.
  4686.  
  4687. There are no limitations to the amount of menus you can use. The
  4688. menus can be connected to arbitrary depth.
  4689.  
  4690. The menus 'remember' which option was selected the last time the user
  4691. was browsing through it. This option is again highlighted when the
  4692. menu is entered.
  4693.  
  4694. Function protypes are in csmenu.h.
  4695.  
  4696.  
  4697. 26.2 Defining a menu
  4698.  
  4699. int type(int hor_or_ver)
  4700.         Sets the type of the menu. There are two types:
  4701.         horizontal or vertical. In CSMENU.H two constants
  4702.         are predefined:
  4703.         MENU_HOR for a horizontal menu and
  4704.         MENU_VER for a vertical menu.
  4705.         The default is MENU_VER.
  4706. void hold(int HoldRelease)
  4707.         A menu can be permanent on the screen or can be
  4708.         automatically removed after being used. This function
  4709.         allows you to control this. In CSMENU.H two
  4710.         constants are predefined:
  4711.         MENU_HOLD makes the menu remain on the screen
  4712.             and
  4713.         MENU_RELEASE which removes the menu
  4714.             afterwards.
  4715.         The default is MENU_RELEASE.
  4716. void relative_pos(int ScreenCursor)
  4717.         The position of the menu can be set relative to the
  4718.         screen or relative to the cursor position at the
  4719.         moment of creation. ( Relative to the cursor is very
  4720.         convenient for submenus. ) In CSMENU.H two
  4721.         constants are predefined:
  4722.         TO_SCREEN for positions relative to the screen and
  4723.         TO_CURSOR for positions relative to the cursor.
  4724.         The default is TO_SCREEN.
  4725. void top(int w)
  4726. void left(int w)
  4727.         Sets the left column and the top row of the left-top
  4728.         corner of the menu. The coordinates are relative to
  4729.         the screen or the cursor, depending on the
  4730.         application of the relative_pos() function. If
  4731.         relative_pos is set to TO_SCREEN a value of -1 will
  4732.         center the menu.
  4733. void width(int)
  4734. void height(int)
  4735.         Sets the height and the width of the menu. If you
  4736.         don't use them or use zero, the appropriate values
  4737.         are calculated automatically. Advise: don't use them.
  4738. int add_option(char *option,int key)
  4739.         Adds an option to the menu. The order in which they
  4740.         appear in the menu is the same as the order in which
  4741.         they are defined. The string 'option' defines the
  4742.         option-string. You can use a '~' to assign a key to the
  4743.         option. The return value is the value 'key'.
  4744.  
  4745.  
  4746.         Example:
  4747.         MENU m1;
  4748.         m1.add_option(" Se~tup ",123);
  4749.         // Defines option ' Setup ' as the first option
  4750.         // of menu m1. This option can also (apart
  4751.         // from using the cursor keys) being
  4752.         // selected by pressing 't' or 'T'.
  4753.         // If chosen, the menu system will return
  4754.         // the value 123.
  4755.  
  4756.  
  4757. void enable_option(int num,int YesNo)
  4758.         With this function you control whether-or-not an
  4759.         option can be selected.
  4760.         Parameters:
  4761.         num Option number 'num'. The first option is
  4762.             number ONE.
  4763.         YesNo    YesNo=TRUE means option is selectable.
  4764.             YesNo=FALSE means option can NOT
  4765.             being selected.
  4766.         By default all options are enabled.
  4767. void enable_option(int YesNo)
  4768.         The same as the previous function, but applied to the
  4769.         last added option.
  4770. void border_color(int)
  4771. void screen_color(int)
  4772. void option_color(int )
  4773. void key_color(int )
  4774.         Sets the screen ATTRIBUTE of respectively the
  4775.         -border of the menu,
  4776.         -the 'normal' text in the menu, the not selected
  4777.             options.
  4778.         -the option which is currently selected
  4779.         -the hot key connected with the option
  4780.         Acceptable defaults are provided, depending on the
  4781.         type of screen.
  4782. void color(int border, int screen, int option, int key)
  4783.         Sets all four colors at once.
  4784.  
  4785.  
  4786. 26.3 Connecting menus
  4787.  
  4788. The previous described functions are all concerned with defining just
  4789. one menu. Of course you want to use a more complex menu structure
  4790. which includes several sub-menus. The method to accomplish this is a
  4791. simple one. Just define all submenus with the previously mentioned
  4792. functions and then 'connect' them by calls to the connect(int, MENU &)
  4793. function.
  4794.  
  4795. int connect(int num, MENU &m2)
  4796.         Makes menu 'm2' a sub menu of this menu, 'dangling'
  4797.         under option 'num'. The first option is number ONE.
  4798.  
  4799.  
  4800.        Example:
  4801.            #include "cswindow.h"
  4802.            #include "cskeys.h"
  4803.            #include "csmenu.h"
  4804.  
  4805.            MENU m1,m2;
  4806.            m1.add_option(" File ", ALT_F);
  4807.            m1.add_option(" Setup ",ALT_S);
  4808.            m1.type(MENU_HOR);
  4809.            m1.left(1);
  4810.            m1.top(1);
  4811.            m1.border(BORDER_NONE);
  4812.            m2.add_option(" ~Load ", F3);
  4813.            m2.add_option(" ~Save ", F2);
  4814.            m2.left(1);
  4815.            m2.top(1);
  4816.            m2.relative_pos(TO_CURSOR);
  4817.            m1.connect(1,m2);
  4818.  
  4819.  
  4820.  
  4821. 26.4 Displaying the menu
  4822.  
  4823. void standby(void)
  4824.         If the menu is defined, it can be put on the screen by
  4825.         calling the standby() function. This will make all the
  4826.         (sub-) menus which are defined with MENU_HOLD
  4827.         become visible.
  4828.  
  4829.  
  4830. 26.5 Using menus
  4831.  
  4832. There are two ways to use the menu system:
  4833.  
  4834. 1) The straightforward method.
  4835.         This is by a call to:
  4836.             int rc=choose(int &option).
  4837.  
  4838.         The user can select an option by using the cursor
  4839.         keys, escape, enter etc..
  4840.  
  4841.         Afterwards rc indicates the way the menu is left.
  4842.         If rc==ESC the menu is left by pressing the escape
  4843.         key, 'option' is undefined.
  4844.         If rc==ENTER the menu is left by pressing 'enter',
  4845.         and 'option' contains the return value corresponding
  4846.         with the selected option.
  4847. 2) The hard way.
  4848.         In some, more complicated, cases the simple
  4849.         choose() function will not do, as is made clear by the
  4850.         following problem.
  4851.  
  4852.         Problem:
  4853.             Let's say you have a program in which the user
  4854.             can load a file by pressing F3. He also can reach
  4855.             the same option by browsing through the menus.
  4856.             Typically you want the load option to remain
  4857.             highlighted on the screen while your user is
  4858.             typing in the file name. How to accomplish this?
  4859.         Solution:
  4860.             The int show(int key) function is intended to
  4861.             solve this problem. Show(key) searches through
  4862.             the menus looking for the value 'key'. It returns
  4863.             TRUE if 'key' is found, FALSE otherwise.
  4864.             Assuming the required value is found, all the
  4865.             involved (sub-)menus are automatically
  4866.             displayed. Afterwards things can be brought back
  4867.             to normal by a call to standby().
  4868.  
  4869.           Example:
  4870.  
  4871.          #include "cswindow.h"
  4872.          #include "cskeys.h"
  4873.          #include "csmenu.h"
  4874.  
  4875.          MENU m1,m2;
  4876.          m1.add_option(" File ", ALT_F);
  4877.          m1.add_option(" Setup ",ALT_S);
  4878.          m1.type(MENU_HOR);
  4879.          m1.left(1);
  4880.          m1.top(1);
  4881.          m1.border(BORDER_NONE);
  4882.          m2.add_option(" ~Load ", F3);
  4883.          m2.add_option(" ~Save ", F2);
  4884.          m2.add_option(" e~Xit ", ALT_X);
  4885.          m2.left(1);
  4886.          m2.top(1);
  4887.          m2.relative_pos(TO_CURSOR);
  4888.          m1.connect(1,m2);
  4889.  
  4890.          m1.standby();  // Finally display something.
  4891.  
  4892.          int key;
  4893.          do
  4894.          {
  4895.            key=cskey();   // Read a key
  4896.            // ESC means browsing through the menus.
  4897.            if(key==ESC) m1.choose(key);
  4898.            // key now contains the option, either
  4899.            // by directly typing it in or selected
  4900.            // from the menu.
  4901.  
  4902.         switch(key)
  4903.            {
  4904.          case F3:   // Loading a file.
  4905.           m1.show(F3);
  4906.           // Both the menus are now being
  4907.           // displayed.
  4908.           // The option 'load' is highlighted.
  4909.           //
  4910.           // You can now call the load function.
  4911.           load_function();   // Not defined.
  4912.           //
  4913.           m1.standby();
  4914.           // Bring the menu system back in its
  4915.           // default status.
  4916.           break;
  4917.          case F2:   // Saving a file.
  4918.           // some
  4919.           // code to
  4920.           // save.
  4921.           break;
  4922.            }
  4923.          } while (key!=ALT_X);  // Use ALT_X to terminate loop.
  4924.  
  4925.  
  4926.  
  4927. Syntax:
  4928.  
  4929. int choose(int &option)
  4930.         Use: int rc=choose(option);
  4931.  
  4932.         The user can select an option by using the cursor
  4933.         keys, escape, enter etc.. Afterwards rc indicates the
  4934.         way the menu is left. If rc==ESC the menu is left by
  4935.         pressing the escape key and 'option' is undefined. If
  4936.         rc==ENTER the menu is left by pressing 'enter', and
  4937.         'option' contains the return value corresponding with
  4938.         the selected option.
  4939. int choose_hold(int &option)
  4940.         Same as choose() but the selected option and the
  4941.         selected (sub)-menu(s) remain visible after the
  4942.         function has returned.
  4943. int show(int key)
  4944.         Show(key) searches through the menus looking for
  4945.         the value 'key'. It returns TRUE if 'key' is found,
  4946.         FALSE otherwise. Assuming the required value is
  4947.         found, all the involved (sub-)menus are automatically
  4948.         displayed. Afterwards things can be brought back to
  4949.         normal by a call to standby().
  4950.  
  4951.  
  4952. 26.6 Removing the menu
  4953.  
  4954. void remove(void)
  4955.         By calling the remove() function the menu, including
  4956.         all sub-menus, will be removed.
  4957.  
  4958.  
  4959.  
  4960.  
  4961.                   27 CSPANEL
  4962.  
  4963.  
  4964. 27.1 Purpose
  4965.  
  4966. The PANEL class is intended to provide data entry screen much like
  4967. the ones used by dBASE.
  4968.  
  4969.  
  4970. Class name: PANEL
  4971. Prototypes: cspanel.h.
  4972.  
  4973. 27.2 General Information
  4974.  
  4975.     - This class is publicly derived from the window class. This implies
  4976.     that you can use all the functions from the window class to
  4977.     manipulate the panel window.
  4978.     - The default panel will appear both horizontally- and
  4979.     vertically-centered. The destructor of the class will remove, if
  4980.     needed, the panel and all fields.
  4981.     - The maximum number of fields in the panel is set to 35 by a
  4982.     preprocessor constant MAX_FIELDS. This value can NOT be
  4983.     increased. The variable is defined in the CSPANEL.H file.
  4984.     - The fields are numbered. The first field is numbered ZERO.
  4985.     - Fields can be made 'protected'. This means you cannot alter the
  4986.     contents of the field. The protection can be changed between
  4987.     successive calls to the read function (see below).
  4988.     - A 'changed' function is provided to determine whether-or-not
  4989.     something has been altered.
  4990.     - Functions are available to set the EXIT key and the EXIT field(s).
  4991.  
  4992.  
  4993. 27.3 Public member functions
  4994.  
  4995. void field_color(int col_att)
  4996.         Sets the default text ATTRIBUTE of each new added
  4997.         field.
  4998.         Meaning:    each field which is added to the panel
  4999.                 after a call to field_color() gets color
  5000.                 col_att, unless this color is explicitly
  5001.                 overwritten.
  5002. int field_color(void)
  5003.         Returns this field attribute.
  5004. void color(int border,int screen,int field)
  5005.         Sets the colors of the border, the screen and the
  5006.         field.
  5007. int add_field(    int top,
  5008.         int left,
  5009.         int color,
  5010.         int length,
  5011.         TYPE&PARM)
  5012.         This function adds an additional field to the panel.
  5013.         The function returns the number of fields defined so
  5014.         far (including the one you just added.)
  5015.         Parameters:
  5016.         top:        The row of the field, relative to the panel.
  5017.         left:        The left column of the field, relative to the
  5018.                 panel.
  5019.         color:    The color ATTRIBUTE of the field.
  5020.         length: The number of positions of the field.
  5021.         TYPE&PARM:  One of the following:
  5022.             TYPE    PARM
  5023.             char    *s    For a string field
  5024.             int     &i    For an integer field.
  5025.             long    &l    For a long field.
  5026.             float   &f    For a floating point field.
  5027.             double  &d    For a double field.
  5028.  
  5029. int read(void)
  5030.         When the panel is adequately defined, the panel-user
  5031.         can be given control by a call to read(). The function
  5032.         returns when the user hits the exit-key or the ESC
  5033.         key. FALSE is returned if the panel is left by ESC,
  5034.         TRUE otherwise.
  5035. int changed(void)
  5036.         Returns TRUE if the panel is actually changed during
  5037.         the last read. If nothing is changed, the function
  5038.         returns FALSE.
  5039. int protect(int ebd)
  5040.         Intended to create a field which can NOT be edited.
  5041.         There are three options:
  5042.         - EDIT        The default, the field can be edited.
  5043.         - BROWSE    The cursor will not skip this field and
  5044.                 you can let the string scroll but are not
  5045.                 allowed to alter the contents.
  5046.         - DISPLAY   The cursor will skip this field. The initial
  5047.                 value will be displayed. This is applied
  5048.                 to the last added field.
  5049.         The return value is TRUE if successful, FALSE
  5050.         otherwise.
  5051. int protect(int FieldNum, int ebd)
  5052.         Same as protect(int ebd) but applied to field
  5053.         FieldNum.
  5054. int exit_key(int KEY)
  5055.         Sets the key which makes the panel become
  5056.         'accepted'. The default is ENTER in which case the
  5057.         ENTER key cannot be used to skip from one field to
  5058.         another. The ESC-key will always terminate the panel
  5059.         and will make the read function returns FALSE. The
  5060.         allowable keys are the ones defined in CSKEYS.H.
  5061. int exit_field(int FieldNum, int YesNo)
  5062.         Normally the panel can be terminated no matter on
  5063.         which field the cursor is placed. After a call to
  5064.         exit_field(), the panel can only be terminated with the
  5065.         cursor    standing on a field which is marked as an
  5066.         'exit-field'.
  5067.         Calling exit_field(FieldNum,TRUE) marks field
  5068.         FieldNum as 'exit-field. Exit_field(FieldNum,FALSE)
  5069.         removes the mark.
  5070. int exit_field(int YesNo)
  5071.         Same as exit_field(FieldNum,YesNo) except that it is
  5072.         applied to the last added field.
  5073. void escape_off(void)
  5074. void escape(int True_of_False)
  5075. void escape_on(void)
  5076.         Escape_off() or escape(FALSE) disable the escape
  5077.         key. The panel can only be left by the 'exit-key'.
  5078.         Escape_on() or escape(TRUE) enables the escape
  5079.         key. This means the panel can be left by hitting
  5080.         escape.
  5081. void remove(void)
  5082.         Remove the panel and all fields. All dynamically
  5083.         allocated memory is freed. This is also done by the
  5084.         destructor off the class.
  5085. void date(int type)
  5086.         All the basic data types are automatically recognised
  5087.         by the add_field function. This is not so for dates. If
  5088.         you want a string to be treated as a date you have to
  5089.         call this function after the add_field() function.
  5090.  
  5091.  
  5092. 27.4 Dates
  5093.  
  5094. This paragraph describes the value of 'type' in the date(type) function.
  5095.  
  5096. There are several different formats supported:
  5097. Formats and the examples for April/25/1993.
  5098.  
  5099. The formats are build out of:
  5100. M   Month
  5101. D   Day
  5102. Y2  Year 2 positions
  5103. Y4  Year 4 positions
  5104.  
  5105.         FORMAT: EXAMPLE:
  5106.  
  5107.         MDY2        04/25/93
  5108.         MY2D        04/93/25
  5109.         Y2MD        93/04/25
  5110.         Y2DM        93/25/04
  5111.         DMY2        25/04/93
  5112.         DY2M        25/93/04
  5113.         MDY4        04/25/1993
  5114.         MY4D        04/1993/25
  5115.         Y4MD        1993/04/25
  5116.         Y4DM        1993/25/04
  5117.         DMY4        25/04/1993
  5118.         DY4M        25/1993/04
  5119.  
  5120. EXAMPLE:
  5121.  
  5122.      main(void)
  5123.      {
  5124.  
  5125.        char date_field[]="25/04/93";
  5126.        PANEL pan;
  5127.        pan.add_field(4,6,date_field);
  5128.        pan.date(MDY2);
  5129.  
  5130.      }
  5131.  
  5132.  
  5133.  
  5134. 27.5 Fields
  5135.  
  5136. The fields in the panel are instances of an independent class. They are
  5137. derived from both the WINDOW class and the EDSTR class. This
  5138. means that  you can apply all the functions from these classes to each
  5139. field independently.
  5140.  
  5141. The modify a field you have the use the mod_field macro.
  5142.  
  5143.  
  5144.       EXAMPLE:
  5145.        // Suppose you want to change the color of a
  5146.        // specific field.
  5147.  
  5148.        #include "cspanel.h"
  5149.  
  5150.        main(void)
  5151.        {
  5152.  
  5153.       float balance=-345.87;
  5154.       int c_in_debt=make_color(RED,BLACK);
  5155.  
  5156.       PANEL pan;
  5157.       pan.add_field(2,3,10,balance);
  5158.       if(balance<0)
  5159.       { // display the figures in red if the
  5160.         // balance is negative.
  5161.         pan.mod_field.text_color(c_in_debt);
  5162.       }
  5163.  
  5164.        }
  5165.  
  5166.  
  5167.  
  5168.  
  5169.  
  5170. The purpose of the macro is to hide a peculiar syntax.
  5171.  
  5172. The 'pan.mod_field.text_color(c_debt)' is expanded into:
  5173.         pan.field().text_color(c_debt)
  5174.  
  5175. If you have no objection against a syntax like that you can use it
  5176. directly. In fact, if you want to change a field other then the last-added
  5177. you have to use the function:
  5178.  
  5179.         FIELD& field(int num)
  5180.  
  5181.  
  5182.       EXAMPLE:
  5183.      // Suppose you want to put a border around field number
  5184.      // three ( Remember the first field is field ZERO.)
  5185.  
  5186.      PANEL pan;
  5187.  
  5188.      pan.add_field.....   //  Adding
  5189.      pan.add_field.....   //  Some
  5190.      pan.add_field.....   //  Fields
  5191.      pan.add_field.....   //
  5192.      pan.add_field.....   //
  5193.  
  5194.      pan.field(3).border(BORDER_SINGLE);
  5195.      // Change the color of the fourth field
  5196.  
  5197.  
  5198.  
  5199.  
  5200.  
  5201. Functions:
  5202.         FIELD& field(void)  To change the last added field.
  5203.         FIELD& field(int num)    To change field 'num'.
  5204. Macro:
  5205.         mod_field        Same as field().
  5206.  
  5207.  
  5208. 27.6 Using the panels
  5209.  
  5210. A panel basically consists of a window and a number of fields. The
  5211. fields can be changed by the 'mod_field' macro and the shape and size
  5212. of the panel-window can be altered with the functions from the
  5213. WINDOW class. However there is no special function to add normal
  5214. text in the panel. Of course this is not needed because the normal
  5215. gotoxy() and cprintf() functions can be used for that. But don't forget to
  5216. 'activate' the panel before you write text in it.
  5217.  
  5218.     Example:
  5219.  
  5220.     #include "cspanel.h"
  5221.     main(void)
  5222.     {
  5223.  
  5224.        char str[]=" Some string ";
  5225.        char da[]="30/03/1987";
  5226.        PANEL panel;
  5227.  
  5228.        panel.set_dim(-1,-1,13,55);        // These are
  5229.        panel.head(" A demo  ");         // all functions
  5230.        panel.border(BORDER_DOUBLE);     // from the WINDOW class.
  5231.  
  5232.        panel.activate();            // DON'T FORGET THIS !!!
  5233.                         // The panel is now visible
  5234.                         // (Although without fields)
  5235.        gotoyx(2,10); cprintf("String: ");   // Put text in the panel.
  5236.        panel.add_field(2,20,25,str);    // Add a field.
  5237.  
  5238.        gotoyx(7,10); cprintf("Date: "); // Put text in the panel.
  5239.        panel.add_field(7,20,da);        // Add a date field.
  5240.        panel.date(DMY4);            // Date Format.
  5241.        panel.exit_key(F10);         // Leave panel with F10.
  5242.  
  5243.        panel.read();            // Edit the data.
  5244.  
  5245.     }
  5246.  
  5247. // Note: gotoyx() is used instead of gotoxy().
  5248. // This is easier because the coordinates of the
  5249. // add_field() functions also work in that way.
  5250.  
  5251.  
  5252.  
  5253. 27.7 Data validation
  5254.  
  5255. At the moment of writing the capabilities for data validation are limited.
  5256. There exists a option to supply a maximum and a minimum value.
  5257. Apart from that, there is a 'picture()' function to supply some crude sort
  5258. of template. It isn't perfect, but it will do in most cases.
  5259.  
  5260. Without 'anything' the next table applies:
  5261.  
  5262.     date:   Are validated correctly, including leap-years.
  5263.     int:    Accepts everything between -99999 and 99999.
  5264.     long:   Accepts everything between -9999999999 and
  5265.         9999999999.
  5266.     float and double:
  5267.         No checks for precision underflow or overflow. Accepts
  5268.         exponents between -999 and +999. No limits to the
  5269.         number of digits in the mantissa.
  5270.     string: No limitations.
  5271.     char:   Everything of length 1 is accepted.
  5272.  
  5273.  
  5274. When the user is editing a field, he/she is only allowed to skip to the
  5275. next field if the value is considered 'valid'.
  5276. When the 'escape' key is not disabled, the user can leave the panel
  5277. with invalid values by hitting 'escape'.
  5278.  
  5279.  
  5280. 27.7.1 Min and Max
  5281.  
  5282. Syntax: void set_max(...);
  5283.     void set_min(...);
  5284.  
  5285.  
  5286. Every type of field has its own set of functions to supply a maximum
  5287. and a minimum value. These are inline functions which accept a type of
  5288. parameter which may differ from the field type as long as it makes
  5289. sence. E.g. a field of type 'long' has a set_max() function which accepts
  5290. a 'int' but does not have a function which accepts a string.
  5291.  
  5292.  
  5293.  
  5294. // Example Data Validation
  5295.  
  5296. #include "csa.h"
  5297.  
  5298. void main(void)
  5299. {
  5300.  
  5301.     PANEL panel;
  5302.     int value=125;
  5303.  
  5304.     panel.set_dim(-1,-1,19,75);     // Centre the panel on the screen.
  5305.     panel.head(" Data Validation  ");
  5306.     panel.border(BORDER_DOUBLE);
  5307.     panel.activate();
  5308.  
  5309.     gotoyx(6,10); cprintf("Integer field ");
  5310.     panel.add_field(6,30,4,value);  // Use 4 positions to edit 'value'.
  5311.     panel.mod_field.set_max(399);   // Set the maximum value to 399.
  5312.     panel.mod_field.set_min(99);    // Set the minimum value to 99.
  5313.  
  5314.     panel.read();            // Do the editing.
  5315.  
  5316. }
  5317.  
  5318.  
  5319.  
  5320. 27.7.2 Reset Max & Min
  5321.  
  5322. Syntax: void reset_max(void);
  5323.     void reset_min(void);
  5324.  
  5325. When the maximum or the minimum value is no longer required, it can
  5326. be removed by a call to reset_max() or reset_min().
  5327.  
  5328.  
  5329.  
  5330. // Example Reset max & min
  5331.  
  5332. #include "csa.h"
  5333.  
  5334. void main(void)
  5335. {
  5336.  
  5337.     PANEL panel;
  5338.     int value=125;
  5339.  
  5340.     panel.set_dim(-1,-1,19,75);     // Centre the panel on the screen.
  5341.     panel.head(" Data Validation  ");
  5342.     panel.border(BORDER_DOUBLE);
  5343.     panel.activate();
  5344.  
  5345.     gotoyx(6,10); cprintf("Integer field ");
  5346.     panel.add_field(6,30,4,value);  // Use 4 positions to edit 'value'.
  5347.     panel.mod_field.set_max(399);   // Set the maximum value to 399.
  5348.     panel.mod_field.set_min(99);    // Set the minimum value to 99.
  5349.  
  5350.     panel.read();            // Do the editing.
  5351.  
  5352.     panel.mod_field.reset_max();    // Reset the maximum value.
  5353.     panel.mod_field.reset_min();    // Reset the minimum value.
  5354.  
  5355.     panel.read();            // Edit again.
  5356.  
  5357.     panel.remove();             // Remove the panel from the screen.
  5358.  
  5359. }
  5360.  
  5361.  
  5362. 27.7.3 Templates
  5363.  
  5364. Templates are used to specify more accuretly the format of the field.
  5365. This is done by describing the field position-by-position.
  5366.  
  5367. Next is a table indicating which symbols can be used in the template
  5368. and what they mean.
  5369.  
  5370.     n        0123456789-+    Blank allowed.
  5371.     N        0123456789-+    Blank NOT allowed.
  5372.     o        0123456789        Blank allowed.
  5373.     O        0123456789        Blank NOT allowed.
  5374.     p         123456789-+    Blank allowed.
  5375.     P         123456789-+    Blank NOT allowed.
  5376.     q         123456789        Blank allowed.
  5377.     Q         123456789        Blank NOT allowed.
  5378.     s         -+         Blank allowed.
  5379.     S         -+         Blank NOT allowed.
  5380.     A         The characters from the alfabet. Blanks NOT allowed.
  5381.     a         The characters from the alfabet including blanks, ,.;: etc.
  5382.     B         A but displayed as capital. (Not implemented yet.)
  5383.     b         a but displayed as capital. (Not implemented yet.)
  5384.     C         A or O
  5385.     c         a or n
  5386.  
  5387. Or in a table:
  5388.  
  5389. ╔════════╤═══════╤════════╤═════════╤═════════╤════════════════╤══════════════╗
  5390. ║     │ 12345 │    0   │  +-     │  blank  │  abcdefghijk   │   ~`!@#$%^   ║
  5391. ║     │ 6789  │      │        │          │   lmnopqrstu   │ &*()_=|\}{[]"║
  5392. ║     │     │      │        │          │     vwxyz      │   :;'?><,./  ║
  5393. ╟────────┼───────┼────────┼─────────┼─────────┼────────────────┼──────────────╢
  5394. ║   n     │   x     │    x   │   x     │     x    │            │          ║
  5395. ╟────────┼───────┼────────┼─────────┼─────────┼────────────────┼──────────────╢
  5396. ║   N     │   x     │    x   │   x     │          │            │          ║
  5397. ╟────────┼───────┼────────┼─────────┼─────────┼────────────────┼──────────────╢
  5398. ║   o     │   x     │    x   │        │     x    │            │          ║
  5399. ╟────────┼───────┼────────┼─────────┼─────────┼────────────────┼──────────────╢
  5400. ║   O     │   x     │    x   │        │          │            │          ║
  5401. ╟────────┼───────┼────────┼─────────┼─────────┼────────────────┼──────────────╢
  5402. ║   p     │   x     │      │   x     │     x    │            │          ║
  5403. ╟────────┼───────┼────────┼─────────┼─────────┼────────────────┼──────────────╢
  5404. ║   P     │   x     │      │   x     │          │            │          ║
  5405. ╟────────┼───────┼────────┼─────────┼─────────┼────────────────┼──────────────╢
  5406. ║   q     │   x     │      │        │     x    │            │          ║
  5407. ╟────────┼───────┼────────┼─────────┼─────────┼────────────────┼──────────────╢
  5408. ║   Q     │   x     │      │        │          │            │          ║
  5409. ╟────────┼───────┼────────┼─────────┼─────────┼────────────────┼──────────────╢
  5410. ║   s     │     │      │   x     │     x    │            │          ║
  5411. ╟────────┼───────┼────────┼─────────┼─────────┼────────────────┼──────────────╢
  5412. ║   S     │     │      │   x     │          │            │          ║
  5413. ╟────────┼───────┼────────┼─────────┼─────────┼────────────────┼──────────────╢
  5414. ║   a     │     │      │   x     │     x    │       x        │       x      ║
  5415. ╟────────┼───────┼────────┼─────────┼─────────┼────────────────┼──────────────╢
  5416. ║   A     │     │      │        │          │       x        │          ║
  5417. ╟────────┼───────┼────────┼─────────┼─────────┼────────────────┼──────────────╢
  5418. ║   c     │   x     │    x   │   x     │     x    │       x        │       x      ║
  5419. ╟────────┼───────┼────────┼─────────┼─────────┼────────────────┼──────────────╢
  5420. ║   C     │   x     │    x   │        │          │       x        │          ║
  5421. ╚════════╧═══════╧════════╧═════════╧═════════╧════════════════╧══════════════╝
  5422.  
  5423.  
  5424.  
  5425. A template can be applied to a field by calling the 'picture()' function.
  5426.  
  5427. Syntax:
  5428.     void picture(char *temp);
  5429.  
  5430. The template itself is respresented as a string.
  5431. When a template string is used, only the first 127 characters
  5432. from the ASCII set can be used (reliable) in editing the field!!
  5433.  
  5434.  
  5435. Example:
  5436.  
  5437. #include "csa.h"
  5438.  
  5439. void main(void)
  5440. {
  5441.  
  5442.     PANEL panel;
  5443.     int value=125;
  5444.  
  5445.     panel.set_dim(-1,-1,19,75);     // Centre the panel on the screen.
  5446.     panel.activate();
  5447.  
  5448.     panel.add_field(6,30,3,value);  // Use 3 positions to edit 'value'.
  5449.     panel.mod_field.picture("QOO"); // A 3 positions integer. No blanks.
  5450.                     // The first pos is not a '0'.
  5451.                     // No -+ allowed/
  5452.  
  5453.     panel.read();            // Do the editing.
  5454.  
  5455.     panel.remove();            // Remove the panel from the screen.
  5456.  
  5457. }
  5458.  
  5459.  
  5460. When a character other then one from the table, appear in the template
  5461. string, this character becomes a mandatory setting of the field at that
  5462. particular position.
  5463.  
  5464.  
  5465. Example:
  5466.  
  5467. PANEL panel;
  5468. char *str;
  5469.  
  5470. .......
  5471. panel.add_field(6,10,9,str);
  5472. panel.mod_field.picture("tel:AAAAA");
  5473. .....
  5474. ...
  5475.  
  5476.  
  5477. In this example the string will be 9 positions of which the first 4 will be
  5478. 'tel:'. The last 5 will be freely editable, although only the characters from
  5479. the alfabet are allowed.
  5480.  
  5481. This setup works fine until you want to use one of the template codes
  5482. as a literal. To facilitate in that, a 'special' character is supplied. This is
  5483. the '@' character.
  5484.  
  5485. E.g.: the template string "phone:AAAAA" will probably not do what you
  5486. want, because the p,o,n are interpreted according to the table above.
  5487. You have to use the string "@ph@o@ne:AAAAA" instead.
  5488.  
  5489. It is possible to supply only a limited number of options at a specific
  5490. position. For this, there is a special 'or' syntax.
  5491.  
  5492.  
  5493. Example:
  5494. ...mod_field.picture("o.oo[e|E]o");
  5495.  
  5496.  
  5497. In this example there has to be a 'e' or a 'E' at the fourth position.
  5498. Nothing else will be allowed.
  5499. The or syntax takes the form of:
  5500.                  [option1|option2].
  5501.  
  5502. The "or's" can be nested:
  5503.  
  5504.  
  5505. Example:
  5506. ...mod_field.picture("[oooooo|o.oo[e|E]o]");
  5507.  
  5508.  
  5509. The length of the options has to be the same. Note that 'e' is
  5510. of the same length as 'E' and 'oooooo'  is 6 positions just as
  5511. 'o.oo[e|E]o'.
  5512.  
  5513. More then two options are also allowed:
  5514.  
  5515.  
  5516. Example:
  5517. ...mod_field.picture("o.oo[f|F|e|E]o");
  5518.  
  5519.  
  5520.  
  5521.                  28 Registration Form
  5522.  
  5523.  
  5524.  
  5525.  
  5526.     Name:    __________________________________________
  5527.  
  5528.     Address:    __________________________________________
  5529.  
  5530.         _____________________________________
  5531.  
  5532.     City/State: __________________________________________
  5533.  
  5534.     Country:    ______________________     Zip: ______________
  5535.  
  5536.     Telephone:    (________)  _________ - ____________________
  5537.  
  5538.  
  5539.     Diskette preference (circle one):        5.25         3.5
  5540.     If it's the same to you, please pick 3.5.
  5541.  
  5542.  
  5543.  
  5544.             Number        Price F     Price $
  5545.                    (Dutch Guilders)  (American Dollars)
  5546.  
  5547.  
  5548.     CS-Libraries    _________   at    f  200.-    or        $ 125.-
  5549.  
  5550.  
  5551.  
  5552.  
  5553.     Total enclosed            f ______    or        $ _____
  5554.  
  5555.  
  5556.  
  5557.  
  5558.     What would you like to see added or changed in the CS-Libraries?
  5559.  
  5560.     _____________________________________________________________
  5561.     _____________________________________________________________
  5562.     _____________________________________________________________
  5563.     _____________________________________________________________
  5564.     _____________________________________________________________
  5565.  
  5566.  
  5567.  
  5568.  
  5569.     Please, send completed form and check or money order to:
  5570.  
  5571.         Combis
  5572.         P.O. Box 3303
  5573.         2280 GH RIJSWIJK
  5574.         The Netherlands
  5575.  
  5576.  
  5577. Note:    If this documentation is more then a year old, it is advisable to
  5578.     obtain a later version. Software, price and even address may
  5579.     have changed!
  5580.